1

I have a store in MobX that handles containing the cart, and adding items to it. However, when that data is updated the components don't re-render to suit the changes. I tried using useEffect to set the total price, however when the cartData changes, the state is not updated. It does work on mount, though.

In another component, I call addItemToCart, and the console.warn function returns the proper data - but that data doesn't seem to be synced to the component. clearCart also seems to not work.

My stores are contained in one RootStore.

import React, {useState, useEffect} from 'react';
import {List, Text} from '@ui-kitten/components';
import {CartItem} from '_molecules/CartItem';
import {inject, observer} from 'mobx-react';

const CartList = (props) => {
    const {cartData} = props.store.cartStore;
    const [totalPrice, setTotalPrice] = useState(0);

    const renderCartItem = ({item, index}) => (
        <CartItem itemData={item} key={index} />
    );

    useEffect(() => {
        setTotalPrice(cartData.reduce((a, v) => a + v.price * v.quantity, 0));
        console.warn('cart changed!');
    }, [cartData]);

    return (
        <>
            <List
                data={cartData}
                renderItem={renderCartItem}
                style={{backgroundColor: null, width: '100%'}}
            />
            <Text style={{textAlign: 'right'}} category={'s1'}>
                {`Total $${totalPrice}`}
            </Text>
        </>
    );
};

export default inject('store')(observer(CartList));
import {decorate, observable, action} from 'mobx';

class CartStore {
    cartData = [];

    addItemToCart = (itemData) => {
        this.cartData.push({
            title: itemData.title,
            price: itemData.price,
            quantity: 1,
            id: itemData.id,
        });
        console.warn(this.cartData);
    };

    clearCart = () => {
        this.cartData = [];
    };

}


decorate(CartStore, {
    cartData: observable,
    addItemToCart: action,
    clearCart: action,
});

export default new CartStore();
Recon
  • 608
  • 9
  • 18
  • So after you add new item, useEffect is not running, right? This is expected since `cartData` never changes, you just adding new items to it, mutating it. And you don't really need useEffect here, you better make `totalPrice` computed property inside your store https://mobx.js.org/refguide/computed-decorator.html – Danila Jun 30 '20 at 09:04
  • @Danila, yes but my components still do not update regardless. Such as the List which directly uses `cartData`. – Recon Jul 01 '20 at 03:44

1 Answers1

0

I have solved the issue by replacing my addItemToCart action in my CartStore with this:

    addItemToCart = (itemData) => {
        this.cartData = [
            ...this.cartData,
            {
                title: itemData.title,
                price: itemData.price,
                quantity: 1,
                id: itemData.id,
            },
        ];
        console.warn(this.cartData);
    };
Recon
  • 608
  • 9
  • 18
  • You have not actually solved it, just made workaround around feature (useEffect) you don't quite understand. It have no purpose in your code and can easily be replaced with `computed`. – Danila Jul 01 '20 at 16:25
  • @Danila yes I updated my code shortly after to utilise `computed`. I believe my issue was that I was directly mutating the state of MobX through `.push`, though, as just moving my totalPrice calculations into a computed function did not work to solve the main issue. – Recon Jul 03 '20 at 03:04