Home > Mobile >  Multiple useSelector overlaps DOM in React JS
Multiple useSelector overlaps DOM in React JS

Time:10-16

I am using two useSelector and surprisingly it overrides the previous state which it is not supposed to happen.

import { fetchProduct } from "features/ProductSlice";
import { fetchCategory } from "features/ProductCategorySlice";

const ProductList = () => {

    const dispatch = useDispatch()

    const { data: products, status } = useSelector((state) => state.product)

    const { data: categories } = useSelector((state) => state.productCategory)

    useEffect(() => {
        const fetchData = async () => {
            try {
                await Promise(dispatch(fetchProduct()))
                dispatch(fetchCategory());
            } catch (error) {
                // handle or ignore errors?
            }
        };

        fetchData();
    }, [dispatch]);

    console.log('from list p ', products.length)
    console.log('from list c ', categories.length)

    ... 
}

Reducer Code:

ProductSlice: https://codefile.io/f/5HjRcFqvLWoutajPIJLq

ProductCategorySlice: https://codefile.io/f/IQLrLy6xC4gALqj254j7

Video Demo: https://screenrec.com/share/IcJyYuvsKU

As the product categories are fetched first, the value of products update with the value of categories (which is weird). Next when products are fetched then products update again. However the products should not update twice and should only update when products data arrives.

The value of console log is same for both cases.

Looking for the kind help !!

CodePudding user response:

Thanks for editing in the slice and thunk code -- that's where your problem is!

Every createAsyncThunk must have a unique action name. These thunks are not part of the slice itself, so they don't get automatically prefixed with the slice name in the way that actions created from your reducers would. You should add in the prefix yourself, using action names like 'productCategory/fetch' and 'product/fetch' to keep them distinct.

(The exact names don't matter. You could use 'fetchCategory' and 'fetchProduct'. You just need to make sure that they are different from each other.)

Right now your fetchCategory and fetchProduct thunks will both dispatch actions with type 'fetch/pending', 'fetch/fulfilled', etc. so they will both match each other's actions and save data to each other's state.


change

export const fetchCategory = createAsyncThunk(
    'fetch',
    async () => {

to

export const fetchCategory = createAsyncThunk(
    'productCategory/fetch',
    async () => {

CodePudding user response:

As the product categories are fetched first, the value of products update with the value of categories (which is weird).

This is something you need to debug in your reducers. If fetching categories only writes to state.productCategory which is separate from state.product, then this shouldn't happen.

Are you sure that by "update" you mean you see products.length being logged with a different value? Because if it's just printing the same value, that's ok. You shouldn't make assumptions about how often the body of your function component is invoked, calling the console.log.

  • Related