Getting Closure with React
What's a closure?
Closures are like a backpack for functions. The backpack holds all of the values the function needs from its original environment, even if it's called in a different place. It gives functions access to all of its belongings no matter where it's called.
Here's a simple code example:
function createCounter() {
let count = 0;
return function () {
count++;
console.log(count);
};
}
const counter = createCounter();
counter(); // Outputs: 1
counter(); // Outputs: 2
counter(); // Outputs: 3
The inner function has a closure (or backpack) that allows it to "remember" the value of count no matter where we call it!
This is a super powerful tool that makes a lot of things possible!
Closures in React
Here's the "React" version of the above code
export function Counter() {
const [count, setCount] = useState(0);
function updateCount() {
setCount(count + 1);
}
return <button onClick={updateCount}>{count}</button>;
}
The closure is what allows updateCount
to remember and access the value of count
and the setCount
function.
React Rendering - a snapshot of the component
export function Counter() {
const [count, setCount] = useState(0);
function updateCount() {
setCount(count + 1);
console.log(count); // what do we get here?
}
return <button onClick={updateCount}>{count}</button>;
}
Now what happens when we log the value of count
after updating it?
It may surprise you - but it's still whatever the value was before you updated it! (i.e. 0 after first clicked)
The reason: React doesn't immediately update count
so we are left with a stale value - in this case, what the count originally was before the update.
Instead, count
(state) won't be updated until React renders the component again.
This is because state behaves like a snapshot