Home > database >  redux toolkit useSelector() inside loop
redux toolkit useSelector() inside loop

Time:12-22

so i have 2 redux state and selectors that is working well. but i want to call the second selector (get the detail list based on category.id) inside map() loop. how can i do that?

const Dashboard = () => {
  const [data, setData] = useState([]);
  const categories = useSelector(viewFinalCategories);
  // categories is loaded well
  
  const createFinalData = () => {
    const finalData = categories.map((category) => {
      return {
        title: category.label,
        category: category,
        data: useSelector(viewInventoriesByCategory(category.id)), // <- error hook cannot called here..
      };
    });
    setData(finalData);
  };

  useEffect(() => {
    createFinalData();
  }, [categories]);

  return (
     // SectionList of RN here...
  )

CodePudding user response:

Since it violates the hook rule, you can't call useSelector inside a function.

the solution is to get the data in the component level and do the filtering inside the function

const {inventories} = useSelector(state => state)

 const createFinalData = () => {
    const finalData = categories.map((category) => {
      return {
        title: category.label,
        category: category,
        data: inventories.filter((item) => item.idCategory === idCategory)
      };
    });
    setData(finalData);
  };

CodePudding user response:

useSelector is a hook and it has to follow hook rules, one of them is it can't be used inside a loop. Instaed, you need move all this logic from component to yet another selector. I would use createSelector from reselect in this case since you can combine selecting categories into newly created selectFinalData:

import { createSelector } from 'reselect'

const selectFinalData = () =>
  createSelector(
    viewFinalCategories,
    (state, categories) => categories.map((category) => ({
      title: category.label,
      category: category,
      data: viewInventoriesByCategory(category.id)),
     })
    )
  )

and use it in component :

const finalData = useSelector(selectFinalData())
setData(finalData);
  • Related