【问题标题】:Why React needs another render to bail out state updates?为什么 React 需要另一个渲染来缓解状态更新?
【发布时间】:2019-10-02 20:11:34
【问题描述】:

考虑以下Component

const Component = () =>{
    const [state, setState] = useState(null)

    const onClick = () => setState('foo')        

    console.log(state)

    return <button onClick={onClick}> Change </button>   
}

  • 在按下按钮之前console 只打印null
  • 第一次按下按钮console 打印foo
  • 第二次按下按钮结束console打印foo
  • 第三次及以后 console 不打印任何内容

我知道console 不会打印任何内容,因为我正在调用setState,传递与当前状态相同的值,而 React 是bailing out the state update。我的问题是关于以下断言

请注意,React 可能仍需要再次渲染该特定组件 在保释之前。这不应该是一个问题,因为 React 不会 不必要地“深入”到树中。如果你做的很贵 渲染时计算,您可以使用 useMemo 优化它们。

为什么需要这个额外的渲染?我的意思是,Object.is 不是在第二次点击后返回false 吗?

【问题讨论】:

标签: reactjs


【解决方案1】:

内部 useState 是一个useReducer,带有一个basicReducer, 挂钩使用更改队列来更新states

AFAIK 在查看代码后,这是队列中没有完全处理 memoizedState 的情况,因为没有使用钩子 useMemo 的精细控制

【讨论】:

  • src 代码的注释“TODO:不确定这是否是所需的语义,但这是我们为 gDSFP 所做的。我不记得为什么了。”罗夫
  • 有趣的视角
【解决方案2】:

我从同一个问题的已删除答案中得到了满意的答案。 d.c 指出 Dan Abrahmov 在 old github issue 中给出了答案。 引用丹:

我认为当时我们决定,在我们再次尝试渲染之前,我们实际上并不知道是否在所有情况下都可以安全退出。这里的“救助”意味着它不会继续渲染孩子。但是可能需要重新运行相同的函数(例如,如果减速器是内联的,并且在下次渲染时重新运行减速器之前我们不知道是否退出)。因此,为了保持一致性,我们总是在渲染阶段在更新时重新运行它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-30
    • 2016-11-04
    • 2017-01-01
    • 1970-01-01
    • 2020-06-21
    • 2020-07-03
    • 2020-11-04
    • 1970-01-01
    相关资源
    最近更新 更多