Behind the Scenes of React useState Hook.
Demystifying React's useState by Rebuilding the Hook from scratch.
Introduction
So every React developer must have used React's useState Hook someday, but if you haven't here's a little intro -
In React, the useState
hook is used inside a Functional Component to declare, read and update state variable.
Syntax -
const [value, setValue] = useState(defaultValue);
Example -
import React, { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<h1>The counter example</h1>
<button onClick={() => setCount(count - 1)}>-</button>
<span>{count}</span>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
);
}
And it Works! ✨✨✨
The simplicity of this hook by simply letting us create a state
by calling a function made me wonder how React does all of this magic.
Let's understand how React handles useState by:
Rebuilding the useState
hook -
What we've observed is useState
is a function that takes value and returns an array of two elememts including a variable having defaultValue
of our state and a function
to update the state something like this:
const useState = (value) => {
function setValue() {
// some logic here...
}
const state = [value, setValue];
return state;
}
Let's figure out what setValue
do?
when we call setValue()
it updates our state's value and most importantly makes the application re-renders,
so that's what we are going to do here too.
const rootEl = document.getElementById("root");
function setValue(newValue) {
value = newValue; // 1. update value
renderReact(); // 2. rerender React
}
function renderReact() {
ReactDOM.render(<App/>,rootEl);
}
And yes, we did both things but still, the count is not getting updated in the browser. Why so?
I smashed my head like a hundred times and finds out It's because every time we call setValue
using Btn Click our useState expects it as a new hook we just want to create and declare a new state for us from defaultValues and returns that.
To better understand this, try pressing +
below and see the console.
You will notice that it's giving the same default state on every Btn click.
To solve this, we need to do three things -
- Declare the
state
outside theuseState
function so that it doesn't get garbage collected when the function completes its execution. - Add up a condition inside
useState
that says don't create a new state if there's already a state. - Instead of assigning the
newValue
tovalue
, assign it tostate[0]
because we know that state has already been initialized.
Let's do it.
...
let state = []; // 1st condition
const useState = (value) => {
if(state.length) // 2nd condition
return state;
function setValue(newValue) {
state[0] = newValue; // 3rd condition
renderReact();
}
...
}
And finally, after a lot of tweaking the code, it is finally working.
PS: This code only works for single useState per Component, If you want to use multiple states check out this awesome talk by Ryan. I assure you it's worth the time.
This definitely is just a broad picture of what useState does. It handles a lot of other things like maintaining hooks Array, memory cells etc.
Conclusion -
We are at the very end of this article and now you may think that I know all about hooks, but really it is just the tip of the iceberg. Understanding the code which we write is definitely an awesome idea. So, I recommend you don't just stop here and check out some of the resources below:
Resources -
That's it for this article, I hope you liked this. Please share your feedback and questions (if any) in replies!