useState

UseState usage

Imagine clickingbuttonWhat happens after that

function App() {
  const [n, setN] = React.useState(0);
  return (
    <div className="App">
      <p>{n}</p>
      <p>
        <button onClick={()= > setN(n + 1)}>+1</button>
      </p>
    </div>
  );
}
Copy the code

Changes the n variable on the page from 0 to 1


Imagine after

Ask yourself a few questions

What happens when setN is executed? Does n change? Will App() be re-executed?

If App() is reexecuted, will the value of n be different each time useState(0) is executed?

You can find the answer with console.log


Analysis of the

setN

SetN will definitely modify x (let’s call this unknown thing x for now), putting n+1 into X

SetN must trigger
render

useState

UseState will definitely read the latest value of n from x

x

Each component has its own data x, which we’ll name state


Try implementing React. UseState

function myUseState(initialValue) {
  var state = initialValue;
  function setState(newState) {
    state = newState;
    render();
  }
  return [state, setState];
}

// render method we will not implement, just let it render
const render = () = > ReactDOM.render(<App />, rootElement);

function App() {
  const [n, setN] = myUseState(0);
  return (
    <div className="App">
      <p>{n}</p>
      <p>
        <button onClick={()= > setN(n + 1)}>+1</button>
      </p>
    </div>
  );
}
Copy the code

It hasn’t changed at all

Because myUseState resets the state

We need a variable that will not be reset by myUseState

The variable is declared outside of myUseState

/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
let _state;
/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *


function myUseState(initialValue) {
  _state = _state === undefined ? initialValue : _state;
  function setState(newState) {
    _state = newState;
    render();
  }
  return [_state, setState];
}

const render = () = > ReactDOM.render(<App />, rootElement);

function App() {
  const [n, setN] = myUseState(0);
  return (
    <div className="App">
      <p>{n}</p>
      <p>
        <button onClick={()= > setN(n + 1)}>+1</button>
      </p>
    </div>
  );
}
Copy the code

UseState as simple as that?

Don’t worry, there are still problems

What if a component uses two Usestates?

Since all data is in _state, it conflicts


Improvement ideas

Make _state an object

For example, _state = {n:0, m:0}

No, because useState(0) doesn’t know whether the variable is called n or m

Make _state an array

For example, _state= [0, 0]

It seems to work. Let’s try it

Multiple useState

/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
let _state = [];
let index = 0;
/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *


function myUseState(initialValue) {
  const currentIndex = index;
  index += 1;
  _state[currentIndex] = _state[currentIndex] || initialValue;
  const setState = newState= > {
    _state[currentIndex] = newState;
    render();
  };
  return [_state[currentIndex], setState];
}

const render = () = > {
  index = 0;
  ReactDOM.render(<App />, rootElement);
};

function App() {
  const [n, setN] = myUseState(0);
  const [m, setM] = myUseState(0);
  console.log(_state);
  return (
    <div className="App">
      <p>{n}</p>
      <p>
        <button onClick={()= > setN(n + 1)}>+1</button>
      </p>
      <p>{m}</p>
      <p>
        <button onClick={()= > setM(m + 1)}>+1</button>
      </p>
    </div>
  );
}
Copy the code

Disadvantages of the _state array scheme

UseState call sequence

If n is the first rendering, m is the second, and k is the third

The second rendering must ensure the exact same order

React does not allow the following code


conclusion

  1. One for each function componentReactnode
  2. Each node is savedstateandindex (This may not be an accurate description, but just to make sure you’re clear about this, it should be something like state.)
  3. useStateWill readstate[index]
  4. indexbyuseStateThe order in which they appear
  5. setStateWill modifyStateAnd triggers an update