Reputation: 39
I have this function:
const [numbers, setNumbers] = useState([]);
const [rows, setRows] = useState([]);
const addRow = () => {
setNumbers([...numbers, numbers.length+1]);
setRows([...rows,
<NewGradeRow key={numbers[numbers.length-1]} number={numbers[numbers.length-1]}/>]);
}
that is supposed to add new rows. It should be adding a new value to the numbers hook, then using the new value in the numbers hook to add a new row in the rows hook. It runs synchronously though and the new row doesn't use the new value given to the numbers hook. How would I fix this?
Upvotes: 1
Views: 490
Reputation: 26
is " NewGradeRow " a jsx component ?? if so i doubt it could be called or stated in setRows state instaed it should be seperated from the setRows state and put in the return statement.
Upvotes: 0
Reputation: 1267
You have some misunderstanding here. First, setNumbers
and setRows
actually run asynchronous, in a sense that they are batched together to change state only once and not individually run and change app state twice. Read this question to understand this issue.
Second, you cannot get the "updated" value of the state immediately. This has somethings to do with closure. Read this question or this article to understand more about this problem. This issue apply for both callback and hooks
Upvotes: 1
Reputation: 371203
Take the new values from the calculation performed (one plus the length of the original numbers
), rather from the numbers
variable (which hasn't updated yet):
const addRow = () => {
const newNum = numbers.length + 1;
setNumbers([...numbers, newNum]);
setRows([...rows,
<NewGradeRow
key={newNum}
number={newNum}
/>
]);
};
You could also use useEffect
to watch for changes to numbers
. Remove the setRows
from addRow
, and do:
useEffect(() => {
const newNum = numbers[numbers.length - 1];
setRows([...rows,
<NewGradeRow
key={newNum}
number={newNum}
/>
]);
}, numbers.length);
(if the length of numbers
can change from other sources as well, you'll have to factor that into the logic)
Upvotes: 1