Reputation: 11
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
Upvotes: 0
Views: 470
Reputation: 4991
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.
Upvotes: 0
Reputation: 3405
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);
Upvotes: 0
Reputation:
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>
Upvotes: 0
Reputation: 15510
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;
Upvotes: 2
Reputation: 505
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
Upvotes: -1
Reputation: 157
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);
Upvotes: 0