useState

95 阅读2分钟

useState

  1. set操作并非立即生效,而是保存在队列中,在下次render时依次调用。state更改后,会触发组件的重新刷新。
  const add = () => {
    setCount((c) => c + 1)
    console.log('2--count', count) // 此时count为旧值,setCount要到下次render才生效
  }
  1. 大部分场景下set中传入值和函数是无区别的,react会保证在下次用户操作前,相应state已经被更新;如用户点击按钮时数字加1,在某次点击后,react会确保下次点击前,本次点击的加1操作已经完成。

  2. state可以为对象和数组,但需要注意把state当成只读对待,不要直接修改对象的键值,而是使用新对象替换旧对象。 直接修改state的键值不会触发re-render。

部分库支持使用直接修改对象键值的方式替代旧对象,如Immer

  1. 当state初始值的计算消耗较大时,使用初始化函数进行初始化,因为初始化函数只会调用一次。

  2. 当组件key为state时,state更新后,组件会重新进行初始化,其内部变量会重置

export default function App() {
  const [version, setVersion] = useState(0);

  function handleReset() {
    setVersion(version + 1);
  }

  return (
    <>
      <button onClick={handleReset}>Reset</button>
      <Form key={version} />
    </>
  );
}

function Form() {
  const [name, setName] = useState('Taylor');

  return (
    <>
      <input
        value={name}
        onChange={e => setName(e.target.value)}
      />
      <p>Hello, {name}.</p>
    </>
  );
}
  1. react在next state与current state相同时做了优化,不进行组件的更新。判断相同的方法是:Object.is。 这也是为什么不能直接修改对象和数组键值的原因,因为无法被Object.is检测出来更新了。

  2. 开发模式 & 严格模式下,组件函数、state的初始化函数和set函数会执行两遍,便于帮助开发者发现代码问题,避免mutation change,保持组件为pure。

function TodoList() {  
    // This component function will run twice for every render.  

    const [todos, setTodos] = useState(() => {  
        // This initializer function will run twice during initialization.  
        return createTodos();  

    });  

    function handleClick() {  
        setTodos(prevTodos => {  

            // This updater function will run twice for every click.  

            return [...prevTodos, createTodo()];  

        });  

    }