Search code examples
reactjsreact-state

Data is not rendering from state in Reactjs



const DataManipulation = ({ data }) => {
  const [taskData, setTaskData] = useState([]);
  const subItemMaker = (subItem, task) => {
    subItem.forEach((sub) => {
      preconditionCheck(sub) &&
        setTaskData(addObjectToArray(taskData, task, sub));
    });
  };
  useEffect(() => {
    console.log(taskData); //Printing the data here
  }, [taskData]);
  const makeUniqueProducts = (dataValues) => {
    dataValues.forEach((dataItem) => {
      subItemMaker(dataItem.subItemValues, dataItem.name);
    });
  };
  
  useEffect(() => {
    makeUniqueProducts(data); //Data changing function
  }, [data]);
  return (
    <>
      {JSON.stringify(taskData)} {/*Here it is not updating */}
    </>
  );
};
export default DataManipulation;

I am making a changes in the data and updating taskData state. It is updating I can see in the useEffect but cant see in the render. Please help me here.


Solution

  • I guess your function is updating taskData multiple times within a loop so React may batch these updates for performance reasons. I'd do somtheing like this:

    import React, { useState, useEffect, useCallback } from 'react';
    
    const DataManipulation = ({ data }) => {
      const [taskData, setTaskData] = useState([]);
    
      const addObjectToArray = useCallback((array, task, sub) => {
        return [...array, { task, sub }];
      }, []);
    
      const subItemMaker = useCallback((subItem, task) => {
    // create a new array of items, then updates the state once with all new items.
        const newItems = subItem.reduce((acc, sub) => {
          if (preconditionCheck(sub)) {
            return addObjectToArray(acc, task, sub);
          }
          return acc;
        }, []);
    
        setTaskData(prevTaskData => [...prevTaskData, ...newItems]);
      }, [addObjectToArray]);
    
      const makeUniqueProducts = useCallback((dataValues) => {
        dataValues.forEach((dataItem) => {
          subItemMaker(dataItem.subItemValues, dataItem.name);
        });
      }, [subItemMaker]);
    
      useEffect(() => {
        makeUniqueProducts(data);
      }, [data, makeUniqueProducts]);
    
      useEffect(() => {
        console.log(taskData);
      }, [taskData]);
    
      return (
        <>
          {JSON.stringify(taskData)}
        </>
      );
    };
    
    export default DataManipulation;
    

    I used the functional form of setTaskData to ensure we're always working with the most up-to-date state.