Tuesday, May 21, 2024
 Popular · Latest · Hot · Upcoming
118
rated 0 times [  121] [ 3]  / answers: 1 / hits: 17829  / 5 Years ago, sat, november 16, 2019, 12:00:00

I am studying react-hook recently. I have encountered a problem which makes me unable to understand in the process of practice.



import React, { useState, useCallback } from 'react';
const set = new Set();

function Demo() {
const [count, setCount] = useState(0);

const changeValue = useCallback(() => {
setCount(count + 1);
}, []);

set.add(count);
console.log('size: ', set.size);

return(
<div>
<p>Hello React Hook</p>
<p>{count}</p>
<button onClick={changeValue}>count++</button>
</div>
)
}

export default Demo;

// If you click the button multiple times, the output is:
// size: 1
// size: 2
// size: 2


I wrote a timer using react-hook. As I expected, the count value shown is always 1, because I didn't use count as a dependency of useCallback.



But what I can't understand is console.log('size: ', set.size) only printed three times, why? Every time I click the count++ button, it will cause the Demo function to re-execute. So every time I click the button, shouldn't console.log('size: ', set.size) will be executed? But in fact it only executed three times.



And why does size keep 2 unchanged? I understand that setCount will replace a new count every time, so size should not increase?



Please help me answer my doubts, thank you very much.



You can test my code here.


More From » reactjs

 Answers
15

The Demo component will re-render whenever its state is changed. So, it will have the size 1 as you have added count state to the set:



set.add(count); // 0 in initial render, size is 1


Now, when you click on the button, it will use the callback useCallback that is memoized by react. It means it will first check if has cached value or not. So, at the first click it has no cached value. And thus it calls its callback to set (update) the count state. Now, count is 1 and you also added the count in to the set.



set.add(count); // 1 in first click, size is 2


On following clicks useCallaback has cached the count value but you have not set the count in second parameter of useCallback hook and thus it will just return the cached value that is 1 - the count state. And it will return always from this. Again I repeat, this time the set size is 2.



You should watch for the changes when put the count state in second argument:



  const changeValue = useCallback(() => {
setCount(count + 1);
}, [count]); // we watch it on every click


Now, you will see the changing value each time you click on the button.






Also note: Don't confuse the changeValue is not being called on following clicks. This calls the useCallback every time but it just doesn't update the state:



  const changeValue = useCallback(() => {
console.log('clicked') // logged every time on button click
setCount(count + 1); // count state is not being watched,
// setCount won't update the count on following clicks
// once it caches the state.
},[]); // need to watch state here to update the state

[#51477] Wednesday, November 6, 2019, 5 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
rickjordond

Total Points: 100
Total Questions: 105
Total Answers: 90

Location: Sweden
Member since Mon, May 8, 2023
1 Year ago
;