Home > Mobile >  how to get around react infinite loop inside map inside useMemo()
how to get around react infinite loop inside map inside useMemo()

Time:01-06

I have looked into the answers for this problem but I am not understanding how it applies to what I am doing, would appreciate some guidance on how to get around this react loop from me setting the state...


  const [budgetYear, setBudgetYear] = useState(0);
  const [budgetMonth, setBudgetMonth] = useState(0);
  const [budgetCustomer, setBudgetCustomers] = useState([] as String[]);

  const test=[{
    "myId": "",
    "myLabel": ""
  }] 

  useMemo(() =>{

    for (const [key, value] of Object.entries(test)) {
      data.push(
        [ 
          'value1',                                                       
          'value2',                 
          'value3'
        ],      

      )

      dateCols.map((date: any, index: any) => { 
        let year = Number(dateCols[index]['name'].split("-")[0])
        let month = Number(dateCols[index]['name'].split("-")[1])

        const writeBudgetItems = () => {
          console.log('writing stuff')
          setBudgetYear(year)
          setBudgetMonth(month-1)
          setBudgetCustomers(['123','234','345','456'])
        }
        writeBudgetItems()
      })
}},[test, dateCols])

CodePudding user response:

useMemo is only for when you want to return a value from the callback, you should be using the useEffect hook for this example. In addition, you shouldn't have the test variable inside the dependency array ([test, dateCols]) since that is causing the infinite re-renders since you're declaring it inside the function component as a normal variable (which means that its value changes each render, causing the useMemo callback to be invoked each time). You should use useState to create the test variable (and the dateCols variable) so they don't trigger the callback in each render:

const [test, setTest] = useState([{
    "myId": "",
    "myLabel": ""
  }])

CodePudding user response:

In your code, you have a loop that iterates over the dateCols array, and inside this loop, you are calling a function writeBudgetItems that sets the state using setBudgetYear, setBudgetMonth, and setBudgetCustomers. Each time the state is set, the component that contains this code will re-render, causing the loop to run again. This can create an infinite loop, as the component will continue to re-render and run the loop indefinitely.

To fix this problem, you can try moving the calls to setBudgetYear, setBudgetMonth, and setBudgetCustomers outside of the loop. For example, you could create a new object that contains the values you want to set, and then set the state using this object after the loop has completed.

Here is an example of how you could modify your code to achieve this:

const [budgetYear, setBudgetYear] = useState(0);
const [budgetMonth, setBudgetMonth] = useState(0);
const [budgetCustomer, setBudgetCustomers] = useState([] as String[]);

const test = [{  "myId": "",  "myLabel": ""}] 

useMemo(() => {
  const budgetData = {
    year: 0,
    month: 0,
    customers: [] as String[]
  };

  for (const [key, value] of Object.entries(test)) {
    data.push(
      [ 
        'value1',                                                       
        'value2',                 
        'value3'
      ],      
    );

    dateCols.map((date: any, index: any) => { 
      let year = Number(dateCols[index]['name'].split("-")[0])
      let month = Number(dateCols[index]['name'].split("-")[1])

      budgetData.year = year;
      budgetData.month = month - 1;
      budgetData.customers = ['123', '234', '345', '456'];
    });
  }

  setBudgetYear(budgetData.year);
  setBudgetMonth(budgetData.month);
  setBudgetCustomers(budgetData.customers);
}, [test, dateCols]);
  • Related