• 关于useState、useEffect的一些误区和心得


    useState

    所有的 state 都是 const

    可以认为每次 Render 的内容都会形成一个快照并保留下来,因此当状态变更而 Rerender 时,就形成了 N 个 Render 状态,而每个 Render 状态都拥有自己固定不变的 Props 与 State。

    <p>You clicked {count} times</p>
    
    • 1

    其中的 count 并非变量、更不是事件监听器之类的东西。每次 setState 的时候,react 直接重新渲染 DOM 树,渲染的时候给 count 赋一个常量的值。

    同样的,props 也是在 render 的时候生成一个新的 const

    useEffect

    与 state 一样,useEffect 本身不涉及事件监听

    每次渲染的时候,effect 的函数对象都是不同的

    每次 render,产生一个新的事件处理函数

    不同次的 render 事件处理函数是独立的

    function Counter() {
      const [count, setCount] = useState(0);
    
      function handleAlertClick() {
        setTimeout(() => {
          alert('You clicked on: ' + count);
        }, 3000);
      }
    
      return (
        <div>
          <p>You clicked {count} times</p>
          <button onClick={() => setCount(count + 1)}>add</button>
          <button onClick={handleAlertClick}>show</button>
        </div>
      );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    点击"add"按钮 3 次,然后点击"show",在 handleAlertClick 等待的 3s 内快速点击 add
    最后 alert 的还是 3,并没有因为 count 改变了而改变

    每次 render,产生一个新的 Effects

    function Counter() {
      const [count, setCount] = useState(0);
    
      useEffect(() => {
        document.title = `You clicked ${count} times`;
      });
    
      return (
        <div>
          <p>You clicked {count} times</p>
          <button onClick={() => setCount(count + 1)}>Click me</button>
        </div>
      );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    上面的 useEffect 在每次 Render 过程中,拿到的 count 都是固化下来的常量

    并不是 count 的值在“不变”的 effect 中发生了改变,而是 effect 函数本身在每一次渲染中都不相同

    第一次 render

    useEffect(() => {
      document.title = `You clicked ${0} times`;
    });
    
    • 1
    • 2
    • 3

    点击后

    useEffect(() => {
      document.title = `You clicked ${1} times`;
    });
    
    • 1
    • 2
    • 3

    再次点击后

    useEffect(() => {
      document.title = `You clicked ${2} times`;
    });
    
    • 1
    • 2
    • 3

    同样的,组件被销毁时执行的那个消除副作用的回调函数,里面的 state 还是创建时的对象

    值得一提的是,消除副作用的时机在下一次绘制 ui 之后,如原 state 为{id: 10},清除并更新 state 为{id: 20}的顺序是这样的:

    1. React 渲染{id: 20}的 UI
    2. 浏览器绘制。我们在屏幕上看到{id: 20}的 UI
    3. React 清除{id: 10}的 effect
    4. React 运行{id: 20}的 effect

    如果用 id 是一个变量的想法去想,id 已经变成 20 了,怎么知道它之前是 10 呢,这是很费解的,但是以“这个 state 是上次 render 的版本”的这种思路来看,就可以理解了

    解决

    有些时候,我们希望获取的是真的当前的值,那么用 ref 就好了

  • 相关阅读:
    buuctf web [极客大挑战 2019]LoveSQL
    cnn 实现图片识别
    小谈设计模式(9)—工厂方法模式
    DIY 一个汽车方向盘游戏外设(MMOS OSW DIY)
    【无源谐波滤波器通常用于电力系统中的谐波抑制】用于抑制电力系统谐波的无源谐波滤波器(Simulink实现)
    Java关于实例对象调用静态变量和静态方法问题
    Linux常用的包管理工具
    云原生之使用Docker部署Mariadb数据库
    2-4.基金的利润分配与税收
    云安全之HTTP协议介绍
  • 原文地址:https://blog.csdn.net/weixin_43544179/article/details/125564475