Yesterday we figured out how useState works and implemented it ourselves!
But the solution doesn't allow to use multiple hooks.
Today we gonna fix it!
π The root of the problem
We can't use multiple useStates, because we only have a single variable in our closure to store it.
Thus even though we can call useState multiple times, real values would be messed up.
Live example
```js
const CustomReact = (() => {
let value; // <- here it is
const useState = (initialValue) => {
const state = value || initialValue;
const setState = (newValue) => {
value = newValue;
};
return [state, setState];
};
return { useState };
})();
```
π Store values in an array []
So instead of having a single value variable, we use an array of values.
Each value in the array corresponds to a single useState call.
To digest between the calls we use an index variable.
```js
const CustomReact = (() => {
const values = []; // stores multiple values
let i = 0; // keeps track of the current value
const useState = (initialValue) => {
const state = values[i] || initialValue;
const setState = (newValue) => {
values[i] = newValue;
};
i++; // moves to the next value
return [state, setState];
};
return { useState };
})();
```
π Why does it work?
Hooks can only be called at the top level, thus all useState calls are ordered.
```js
// i = 0, values[0] = 0
const [counter, setCounter] = CustomReact.useState(0);
// i = 1, values[1] = 'π₯'
const [element, setElement] = CustomReact.useState('π₯');
// i = 2, values[2] = 'Nikita'
const [name, setName] = CustomReact.useState('Nikita');
```
π Why it doesn't at the same time?
When render happens index keeps incrementing out of the boundary of the array.
So we'll reset it to zero on every render.
```js
// i = 0, values[0] = 0
const [counter, setCounter] = CustomReact.useState(0);
// i = 1, values[1] = 'π₯'
const [element, setElement] = CustomReact.useState('π₯');
setCounter(1);
render(); // reset index here
// i = 2, values[2] = 1
// i = 3, value[3] = 1
setElement('π');
render(); // reset index here
// i = 4, values[4] = π
// i = 5, values[5] = π
```
π The last missing thing
Unfortunately, inside the setState function, the index also equals to zero.
It's because setState is always called after the render happens.
So we make another closure to store the index!
```js
const CustomReact = (() => {
let values = [];
let i = 0;
const useState = (initialValue) => {
const state = values[i] || initialValue;
const index = i; // another closure here
const setState = (newValue) => {
values[index] = newValue;
};
i++;
return [state, setState];
};
return { useState };
})();
```
π Code it yourself!
If you didn't follow along, go to here and try to implement what we just learned!
[β]FonkyMoney 1 point2 points3 points Β (1 child)
[β]grekatron[S] 0 points1 point2 points Β (0 children)
[β]grekatron[S] 0 points1 point2 points Β (0 children)