We all know that useState is used to store state. When we call this function, we pass in an initial value. The return value is an array, the first value is the state value, and the second value is the function that sets the state value.

const [count, setCount] = useState(0);
return <div>
    {count}
    <button onClick={()= > {
        setCount(count + 1)
    }}></button>
</div>
Copy the code

Let’s declare the useState function, which returns an array, accepts the initial value, and defines a state variable to store the initial value. Note that the useState method can only be executed once, so we also need to do something about it, leaving the state outside and setting the default if there is a value, and setting the default if there is no value.

After creating a method that sets the state value, return it.

let state;
function useState (initialState) {
    state = state ? state : initialState;
    function setState(newState) {
        state = newState;
    }
    return [state, setState]
}
Copy the code

When we call setState and update the state we need to render the view, i.e. the component needs to be re-rendered. We need to define this method and then call it in the setState method.

function setState(newState) {
    state = newState;
    render();
}
function render() {}Copy the code

ReactDOM is called in the Render method to rerender the view.

function render() {
    ReactDOM.render(<App />.document.getElementById('root'));
}
Copy the code

We have completed the implementation of a basic function, but there is a problem. UseState can set multiple states for many times before, and we can only store one state here, so further modification is needed.

You can change state to an array, and the methods that set state are stored in an array. The correspondence is achieved by subscript.

let state = [];
const setters = [];
let stateIndex = 0;
Copy the code

So we’re going to change the useState code, so we’re going to change the state variable to an array, and we’re going to change the state[stateIndex] as well.

function useState (initialState) {
    state[stateIndex] = state[stateIndex] ? state[stateIndex] : initialState;
    return [state, setState]
}
Copy the code

And then we need to change the location of the setState, so when we change the state we need to pass in the subscript, so we’re going to use the closure to save a copy of each subscript, so that when we click the button we can get the corresponding subscript. We’ll implement a createSetter that takes a subscript as an argument and returns a function that we set as setState. The function receives newState, set to state, index is the index of the closure cache, and then calls Render.

function createSetter (index) {
    return function (newState) { state[index] = newState; render(); }}Copy the code

We can call the createSetter method to get the method that sets the state and stores the index.

function useState (initialState) {
    state[stateIndex] = state[stateIndex] ? state[stateIndex] : initialState;
    const setState = createSetter(stateIndex);
    setters.push(setState);
    return [state, setState]
}
Copy the code

Finally, we have to deal with changes to the setting subscript values. Increment the stateIndex every time we call useState, and we know that useState will be reexecuted every time we call Render, so we reset the stateIndex to 0 in the Render method.

stateIndex++; .function render() {
    stateIndex = 0;
    ReactDOM.render(<App />.document.getElementById('root'));
}
Copy the code

The value returned by useState also needs to be handled, corresponding to the current state value and the method used to set state.

function useState (initialState) {
    state[stateIndex] = state[stateIndex] ? state[stateIndex] : initialState;
    setters.push(createSetter(stateIndex));
    const value = state[stateIndex];
    const setter = setters[stateIndex];
    stateIndex++;
    return [value, setter];
}
Copy the code

And then we’re almost done with the implementation principle.

import React from 'react';
import ReactDOM from 'react-dom';

const state = [];
const setters = [];
let stateIndex = 0;

function createSetter (index) {
    return function (newState) { state[index] = newState; render(); }}function useState (initialState) {
    state[stateIndex] = state[stateIndex] ? state[stateIndex] : initialState;
    setters.push(createSetter(stateIndex));
    const value = state[stateIndex];
    const setter = setters[stateIndex];
    stateIndex++;
    return [value, setter];
}

function render() {
    stateIndex = 0;
    ReactDOM.render(<App />.document.getElementById('root'));
}

const App = () = > {
    const [count, setCount] = useState(0);
    const [name, setName] = useState('yindong');
    return <div>
        {count}
        <button onClick={()= >{ setCount(count + 1); }} ></button>
        {name}
        <button onClick={()= >{ setName('yd'); }} ></button>
    </div>
}

ReactDOM.render(<App />.document.getElementById('root'));

Copy the code