Stale Closures — I underestimated closures
Hello World 🌏
Few months back when I was working in React Class components, I’ve no idea what a stale closure is. Back then here is what I knew about closures:
A closure is a function with some preserved values. the values can be of outer scopes.
The closure is a function that can remember and modify variables from its lexical scope, regardless of execution scope.
Let’s understand closures by a real life analogy.
Suppose you have a magical camera 📷.
The magic is of the camera 📷 is that, any photo 🤳 you take, you can interact with the photo.
Example: You took a photo of a lion 🦁,
Now you have the power
1. to open up the photo and interact with the lion 🦁,
2. you can touch 👆 the lion regardless of your place 🌏 either be in your home 🏠, your grannys home 🏡 or on moon 🌙 .
3. if you apply some filters to the photo, the same filter will get applied to the lion 🐯. Meaning both photo and the lion are connected.
As far as you have your magical camera 📷 you can interact 👆 with the lion 🦁.
If you use a variable which is outside the scope of current function, the snapshot of the variable will be taken.
And the snapshot is not static, just like of the picture of lion. If the value of variable changes, you’ve access to the updated value. Just like you can apply filters to lion, you can update the value of the outside variable.
Consider following code snippet:
In the above example,
count is captured by the returned function from
numberOfYug . As you can see I can read and modify the value.
Let us take another example of async, where I will be calling
incrementYug and still
count variable will be increased by factor of 1.
Now it is pretty much clear that, closure works regardless of there place, and the variables can be accessed outside their execution context.
We can check, if any function has a closure variables or not. Simple do
This was all about closures, now let me explain what I missed to learn about closures.
So this was my understanding about closures.
When moved to functional component in React then I started getting old values while working with hooks and specially timers. Firstly I though it is the problem of React but later learned that this is not a problem. This is how closures work. And I was expericencing the situation called Stale Closure.
Basically a stale closure is a function which is preserving an old value of a variable.
The is may occur due to two reasons:
1. Any other function updated a value in which closed over variable is dependent.
2. The function which is holding closure function (parent) is done executing, while the closure is still hold the old value.
Lets consider below code, which is demonstrating Reason 1:
Can you guess what will be printed in
In the console
Current Yug is 0 will be printed.
How? Due to stale closures.
printYug is holding
message . And value of
message is dependent on
count is updated by another function
Let’s do a
logYug to see what exactly it is holding after calling
increaseYug 3 times.
As you can see, the
logYug (printYug) is preserving old values.
So for this problem we have two solution:
let messageand on every
incrementYugupdate the message.
2. Move the
Now let us see the second reason due to which stale closure condition might occur. The second reason is:
The function which is holding closure function (parent) is done executing, while the closure is still hold the old value.
Consider following code snippet and can you guess what will be printed in console?
In the console
current Yug is 1 will be printed.
The function (incrementYug) which is holding closure function (printYug) is done executing, while we are still keeping the reference of closure function (printYug) which is still holding the old value and still using it.
Here printYug is creating two closures. One with
message and one with
In above code every execution of `incrementYug` is returning new instance of
printYug but we are keeping old instance and using it.
For this problem we have two solution:
1. Finding and Using the fresh instance of closure function (This is done by React in case of hooks)
I hope my experience with closure make you learn something new about closures.