HH123_3 2023-07-13 21:02 采纳率: 86.8%
浏览 84
已结题

阅读Build your own React这篇文章时遇到的问题:它和使用真实的react在某些时候执行结果不同,到底是因为什么?

阅读Build your own React这篇文章时遇到的问题:它和使用真实的react在某些时候执行结果不同,到底是因为什么?

文章链接

分别使用文章中实现的react和真实的react来实现一个组件,该组件包括一个h1,点击h1数字会增加。连续点击该组件两次,看它们的
执行结果。

  1. 利用文章中实现的react实现该组件。完整代码
function Counter() {
  const [state, setState] = Didact.useState(1);
  return (
    <h1 onClick={
      () => {
          setState(c => c + 1)
          setTimeout(() => setState(c => c + 2), 3000)
      }
      
      
      } style="user-select: none">
      Count: {state}
    </h1>
  );
}
const element = <Counter />;
const container = document.getElementById("root");
Didact.render(element, container);

结果:
数字只加1,并没有再加2。

  1. 利用真实的react来实现 完整代码
import { useState } from 'react';

export default function Counter() {
  const [number, setNumber] = useState(0);

  return (
      <h1 onClick={() => {
       setNumber((c) => c + 1)
       setTimeout(() => setNumber((c) => c + 2), 3000)
      }}>
        Count {number}
      </h1>
  )
}

结果:
数字加1之后又加2了。

根据我对文章的理解, setTimeout(() => setNumber(c => c+2), 3000)所修改的Intial render中对应fiber中的hook,而不是在setNumber(c => c + 1)所触发的render中相对应的fiber中的hook,因为两个setNumber都是在initial render时在useState中定义的,我们并没有改变setNumber(c => c+1)所产生的fiber树,即上一次render产生的树,对比是发生在当前正在渲染的树和上一次产生的树之间的,两者并没有发生改变,所以只加了1没有再加2。我还画了帮助理解。但是为什么react既加了1又加了2,我不知道是为什么?两者之间有什么区别?如果第二次渲染复用了第一次渲染的某些fiber节点,那么第二个setNumber是可以改变UI的?

  • 写回答

1条回答 默认 最新

  • RivaJ 2023-07-14 14:11
    关注

    我观察到setTimeout的更新函数被压入了上一次更新的queue中,即与onClick内的setState压入到同一个队列
    而由于setTimeout内到setState触发更新时,上一次reconcile已经完成,本次处理的是alternate下的queue,而它是空的。
    参考如下示意图:

    img


    从这个图也能看到由于你没有在更新后将alternate销毁,导致无限引用,点的次数多了,可能会爆内存。
    大致的解决方向应该是在更新后将alternate销毁,在setState函数调用时,如果检测到已销毁,要尝试获取新的queue,而不是直接从闭包中拿

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 12月17日
  • 已采纳回答 12月9日
  • 创建了问题 7月13日

悬赏问题

  • ¥15 黄永刚的晶体塑性子程序中输入的材料参数里的晶体取向参数是什么形式的?
  • ¥20 数学建模来解决我这个问题
  • ¥15 计算机网络ip分片偏移量计算头部是-20还是-40呀
  • ¥15 stc15f2k60s2单片机关于流水灯,时钟,定时器,矩阵键盘等方面的综合问题
  • ¥15 YOLOv8已有一个初步的检测模型,想利用这个模型对新的图片进行自动标注,生成labellmg可以识别的数据,再手动修改。如何操作?
  • ¥30 NIRfast软件使用指导
  • ¥20 matlab仿真问题,求功率谱密度
  • ¥15 求micropython modbus-RTU 从机的代码或库?
  • ¥15 django5安装失败
  • ¥15 Java与Hbase相关问题