Home > Software engineering >  Too many Re-renders React JS
Too many Re-renders React JS

Time:03-06

Can anyone tell me what is wrong with this code pls ?

    import React, { useState } from "react";

const Createcolumn = () => {
  const [sum, setSum] = useState('');
  const [dailySum, setDailySum] = useState(0);
  const [daysOfWork, setDaysOfWork] = useState(0);
  const [fare, setFare] = useState(0);
  const dailySumHandler = (e) => {
    setDailySum(Number(e.target.value));
  };

  const daysOfWorkHandler = (e) => {
    setDaysOfWork(Number(e.target.value));
  };

  const fareHandler = (e) => {
    setFare(Number(e.target.value));
  };

  setSum(dailySum * daysOfWork   fare);

  return (
    <div>
      <div className="column">
        <h1>Name</h1>
        <h1>Daily</h1>
        <h1>Days of Work</h1>
        <h1>Fare</h1>
        <h1>Total</h1>
      </div>
      <div className="column">
        <div>
          <h1>Nodirbek</h1>
        </div>
        <div>
          <input type="text" onChange={dailySumHandler} />
        </div>
        <div>
          <input type="text" onChange={daysOfWorkHandler} />
        </div>
        <div>
          <input type="text" onChange={fareHandler} />
        </div>
        <div>
          <h1>{sum}</h1>
        </div>
      </div>
    </div>
  );
};

export default Createcolumn;

I cannot set my Sum to h1, it is saying too much render I tried to make a function as well, but it doesn't work either

I cannot set my Sum to h1, it is saying too much render I tried to make a function as well, but it doesn't work either

CodePudding user response:

The problem is you're calling this directly into your render

setSum(dailySum * daysOfWork   fare);

Once setSum gets triggered, it will cause UI re-rendering which calls render function again. And again setSum will continue being called (it's like deadlock)

Here is a possible fix

import React, { useState } from "react";

const Createcolumn = () => {
  const [dailySum, setDailySum] = useState(0);
  const [daysOfWork, setDaysOfWork] = useState(0);
  const [fare, setFare] = useState(0);
  const dailySumHandler = (e) => {
    setDailySum(Number(e.target.value));
  };

  const daysOfWorkHandler = (e) => {
    setDaysOfWork(Number(e.target.value));
  };

  const fareHandler = (e) => {
    setFare(Number(e.target.value));
  };

  return (
    <div>
      <div className="column">
        <h1>Name</h1>
        <h1>Daily</h1>
        <h1>Days of Work</h1>
        <h1>Fare</h1>
        <h1>Total</h1>
      </div>
      <div className="column">
        <div>
          <h1>Nodirbek</h1>
        </div>
        <div>
          <input type="text" onChange={dailySumHandler} />
        </div>
        <div>
          <input type="text" onChange={daysOfWorkHandler} />
        </div>
        <div>
          <input type="text" onChange={fareHandler} />
        </div>
        <div>
          <h1>{dailySum * daysOfWork   fare}</h1>
        </div>
      </div>
    </div>
  );
};

export default Createcolumn;

CodePudding user response:

You can't use calls to hook setters in the body of the function, it'll cause a rerender, which will cause a rerender, which will cause rerender, and so and so forth.

Instead initialize your value when you call the hook: const [sum, setSum] = useState(dailySum * daysOfWork fare);

CodePudding user response:

You have to use arrow function notation while calling those functions and pass the event that's what's causing re-renders.

Your code:

 </div>
        <div>
          <input type="text" onChange={dailySumHandler} />
        </div>
        <div>
          <input type="text" onChange={daysOfWorkHandler} />
        </div>
        <div>
          <input type="text" onChange={fareHandler} />
        </div>

Fix:

 </div>
        <div>
          <input type="text" onChange={(e) => dailySumHandler(e)} />
        </div>
        <div>
          <input type="text" onChange={(e) => daysOfWorkHandler(e)} />
        </div>
        <div>
          <input type="text" onChange={(e) => fareHandler(e)} />
        </div>

CodePudding user response:

The why: You're changing the state in every render not based on some change in your component, remember how react works: you change the state => react re-render your component all over again.

At every render you tell react to change the state(setSum(...)) which will tell react to re-render, all over again, it enters a loop of render and a call to setSum which cause a re-render forever.

Solution: Don't use state if your data can be computed based on other states, it looks like the sum only depends on other states, why create a state for it if you can calculate it easily from other states?

Delete the line:

  const [sum, setSum] = useState('');

and just add the line(before the return statement)

  let sum = (dailySum * daysOfWork   fare);

CodePudding user response:

This is typically the kind of scenario you want to use useMemo to solve:

import { useMemo } from "react"

const sum = useMemo(
    () => dailySum * daysOfWork   fare,
    [dailySum, daysOfWork, fare]
);

This allows you to automatically recompute the sum whenever any of its components changes without having to keep track of an additional state and setter.

CodePudding user response:

The problem here is that when you try to use setstate() before you bring in the return() statement it will bring out that error. The solution is that the setSum() have to fire after the first render after the return statement

  • Related