版本: react@18.3.1

我看源码就是先 UnmountEffects 后 MountEffects,里面也只是递归遍历而已,为什么 cleanup 里面的 props 是上一次的了?

commitPassiveUnmountEffects(root.current);
commitPassiveMountEffects(root, root.current, lanes, transitions);
// 复现的 demo
function App() {
  const [num, setNum] = useState(100)
  window.__setNum = setNum
  return <Comp num={num}></Comp>
}

function Comp(props) {
  debugger
  useEffect(() => {
    debugger
    props // {num:1000}
    return () => {
      debugger
      // 为什么这里是旧的 props? {num:100}
      props
    }
  }, [props.num])
  return (
    <p>
      <span>{props.num}</span>
    </p>
  )
}

setTimeout(() => {
  __setNum(1000)
}, 1000)
举报· 2860 次点击
登录 注册 站外分享
26 条回复  
ltaoo1o 初学 5 天前
@shintendo #25 心智负担,而且代码会比较丑🤣
shintendo 小成 5 天前
@ltaoo1o 容易漏是指漏依赖? eslint 可以检查啊
shintendo 小成 5 天前
@ljpCN 你这个跟他的不一样,他监听了 document ,在输入框外面 enter 也能触发
ljpCN 小成 5 天前
@ltaoo1o 如果你是想要在整个页面监听回车按键,先不讨论这个需求的合理性,为了实现你要的语义清晰,你应该寻求对 hooks 的封装来实现你的 log 函数拿到最新的 state ,或者直接通过 ref 获取 input 标签当前的 value 。前者的话举一个例子: https://ahooks.js.org/hooks/use-memoized-fn
ltaoo1o 初学 5 天前
@ljpCN #21 额,语义是指业务逻辑,就比如我必须表达出「当页面加载后,监听回车」,在这个前提下,如何完成需求,你的代码非常好,没有问题。只是少了「当页面加载后」的这个含义。
ljpCN 小成 5 天前
@ltaoo1o 那给你看看我改完的代码吧,个人觉得比你的语义更清晰。https://codesandbox.io/p/sandbox/zuo-yong-yu-de-wen-ti-forked-6ljjys
ltaoo1o 初学 5 天前
@ljpCN 实现方式其实很多种,难的是保留语义的前提下。我希望我的代码,别人一看,就能明白是「当页面加载后,监听回车事件并 xxx 」,如果写在 input 标签,就变成了「当这个 input 回车时,xxx 」,这里的语义就丢失了。 当然代码能跑就行,「代码表达语义」仅仅是我个人的追求。
ljpCN 小成 5 天前
@ltaoo1o 你应该在 input 标签的 onKeyDown 回调里处理你的键盘监听,而不是在 useEffect 里处理
ltaoo1o 初学 5 天前
@TWorldIsNButThis #16 所以我说函数组件有额外的心智负担,容易出问题,感觉在和框架斗智斗勇 🤣
123下一页
返回顶部