react-useState

102 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

初始值

  1. 初始值只在第一次渲染的时候获取
const [count, setCount] = useState(0);
  1. 可以接受一个值,也可以接受一个函数
const [count, setCount] = useState(() => {
    return 1;
});

不会覆盖

和Class的setState不同,hooks的setState对每个状态都是单独存储的,不会覆盖所有状态,可以同时存在多个state, 每次更新只需要更新各自的state就可以

异步更新的问题

使用setState多次更新时,我们很容易会发现一个问题,当我们setState时如果是在异步的语句中,这个用来计算的值,是当前的值还是上次计算还没回来值。

function App() {
  const [count, setCount] = useState(() => {return 21;});
  const handleClick = () => {
     setTimeout(() => {
      setCount(count + 1);
    },2000)
  };
  console.log(count);
  return (
    <div>
      <button onClick={handleClick}>{count}</button>
    </div>
  );
}

可以发现连续打印两次执行的结果,count依然是1? 这个就是因为,第二次执行时,由于setState(count + 1)更新,是取count当前的值去计算,当前就是点击的时候值,当前的count仍然是0,通过0计算,依然是1。

那如何解决异步问题呢?

setState可以接受一个函数作为参数,函数接收一个参数,这个时候的取值,是每次到执行的时候(2s后)才会去拿的值,就可以得到正确的值了

function App() {
  const [count, setCount] = useState(() => {return 0;});
  const handleClick = () => {
    setTimeout(() => {
      setCount((count) => {
        return count + 1;
      });
    }, 2000);

  };
  console.log(count);
  return (
    <div>
      <button onClick={handleClick}>{count}</button>
    </div>
  );
}

不释放内存

一般来说,函数执行完会释放里面变量的内存,但是hooks中的变量占据的内存不会被释放掉,所以一些没有必要用state的值,没有多次更新,只是取值进行计算的话,是可以减少一些useState的使用。

实现一个简单的useState

只是简单实现以下,不严谨,没有实现,setState和initialState可以接受函数的功能,也没有实现独立存储,不会释放内存等等功能,只是简单实现了更新和取值的功能。


const _states = [];  // 假设为存储state的集合
const index = 0;   // 假设用这个确保每个state的唯一性

function _useState(initialState) {

  index++;
  
  _states[index] = _states[index] || initialState || undefined;

  const _setState = (newState) => {
    _states[index] = newState;
    render();
  }

  return [_states[index], _setState];
}