Skip to content

Instantly share code, notes, and snippets.

@getify
Last active March 28, 2020 14:59
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save getify/74ddbce9effebabacee1dd395d3edb4c to your computer and use it in GitHub Desktop.
Save getify/74ddbce9effebabacee1dd395d3edb4c to your computer and use it in GitHub Desktop.
illustrating the hook/stale-closure problem
function SomeCounter() {
const [ counter, updateCounter ] = useState(0);
useEffect(function listening(){
const btn = document.getElementById("increment-counter-btn");
btn.addEventListener("click",onClick);
},[]);
useEffect(function logger(){
// this logger() is updated each time `counter` changes, so
// the closure is never stale
console.log(`Current counter: ${ counter }`);
},[ counter ]);
return <div>Counter Value: {counter}</div>;
function onClick(evt) {
// we're closed over `counter` here, but only the onClick()
// from the very first rendering is bound as the event
// handler; the closure becomes stale -- OOPS!
console.log(`Previous Counter: ${counter}`);
updateCounter(c => c + 1);
}
}
@getify
Copy link
Author

getify commented Mar 27, 2020

FTR, I'm well aware of myriad ways to "fix" this problem. I'm also well aware of linter rules that purportedly save you from making this mistake. Neither of those is relevant to my point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment