Complex Object updating state, not re-render function
sremiger1 opened this issue · comments
When the object is complex it does not appear to be forcing state to re-render. Am I doing something wrong?
If you un comment the line //setCartListForce(!cartListForce);
everything updates, if you leave it commented the quantity display never updates.
import React from 'react';
import { createStore, useStore } from 'react-hookstore';
export class ProductItem {
key: number;
ProductId?: number;
ProductDescription!: string;
SKU!: string;
Price!: number;
formatPrice() {
return '$' + this.Price.toFixed(2).toString();
}
}
export class CartItem extends ProductItem {
Quantity: number = 0;
}
export class ShoppingCartList {
key: number;
cartItems!: CartItem[];
getTotal(): string {
let sum: number = 0;
if (this.cartItems === null || this.cartItems.length === 0) {
return '$' + sum.toFixed(2).toString();
}
let i: number = 0;
for (i = 0; i < this.cartItems.length; i++) {
let cartItem: CartItem = this.cartItems[i];
if (cartItem.Price && cartItem.Quantity) {
const itemTotal: number = cartItem.Price * cartItem.Quantity;
sum += itemTotal;
}
}
return '$' + sum.toFixed(2).toString();
}
getCartCount(): number {
let total: number = 0;
if (this.cartItems === null || this.cartItems.length === 0) {
return 0;
}
let i: number = 0;
for (i = 0; i < this.cartItems.length; i++) {
let cartItem: CartItem = this.cartItems[i];
if (cartItem.Quantity) {
total += cartItem.Quantity;
}
}
return total;
}
}
const shoppingCartList: ShoppingCartList = new ShoppingCartList();
shoppingCartList.cartItems = [];
createStore('cartListX', shoppingCartList);
createStore('cartListForce', true);
export function Message() {
const[cartList] = useStore<ShoppingCartList>('cartListX');
const[cartListForce] = useStore<ShoppingCartList>('cartListForce');
return (
<div>
{ cartList.getCartCount() }
</div>
);
}
export default function Basic() {
const[cartList, setCartList] = useStore<ShoppingCartList>('cartListX');
const[cartListForce, setCartListForce ] = useStore<boolean>('cartListForce');
const _onClick =() => {
console.log('_onClick');
if (cartList.cartItems.length == 0 ){
console.log('_onClick add item');
let cartItem: CartItem = new CartItem();
cartItem.Price = 1.00;
cartItem.Quantity = 1;
cartList.cartItems.push( cartItem );
}
else{
console.log('_onClick increment');
cartList.cartItems[0].Quantity += 1;
}
console.log('_onClick setList');
setCartList(cartList);
//setCartListForce(!cartListForce);
}
return (
<div>
<button onClick={_onClick}>Click here to Add Quantity</button>
<Message />
</div>
);
}
That is normal within react. Objects and Arrays do not force re-renders as their references do not change.
That's exactly it. Thanks @caryd. You're using a class instance as your state. if you refactor it to be a plain object and replace the object everytime using destructuring assignment (For example: doing this setState({ ...oldState, keyToUpdate: newValue })
it will work.
If you wish to keep using this structure, I suggest using MobX to manage your state, it'll probably be great for you!
Also I have currently a PR opened for a new feature, where you'll be able to tell the library which bits of the state object you're using in each component, it would also help in this case.