我对以下虚拟组件进行了一些测试,在执行过程中(在控制台中),我得到了以下结果:
Rendering: 0
Triggered: 0
Rendering: 4
Triggered: 4
Rendering: 4我很难理解为什么。
首次渲染:
index设置为0。undefined不是0index设置为4第二次渲染:
index是4第三次渲染:
我期望的是:
Rendering: 0
Triggered: 0
Rendering: 4我是不是跳过了很明显的东西?你能帮我理解一下引擎盖下的工作原理吗?
const Example = React.memo(() => {
const [index, setIndex] = React.useState(0)
console.log('Rendering: ', index)
React.useEffect(() => {
console.log('Triggered: ', index)
setIndex(4)
}, [index])
return <h1>{index}</h1>
})
ReactDOM.render(<Example />, document.body);<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
发布于 2022-01-19 10:46:27
重发的数量实际上是正确的。让我们分析一下发生了什么:
useEffect自动运行)useEffect的初始触发index的新状态设置为4index从0更改为44更改为4 (即使值相同,它也会触发组件重发,因为React不知道是否设置了相同的状态,并且需要再次运行)。在这个重命名器中,useEffect不会运行,因为index又是4了。基本原理
如果组件中有任何变化,比如useState useContext、customHook,则该组件将需要重命名。如果父组件重选器,即使组件没有任何更改,子组件也会发生这种情况。
更多的更新提示和信息
为了防止子组件发生父级不必要的重命名,您可以使用React.memo,如果道具发生更改,这将重新更新组件,但如果状态或上述任何挂钩在组件中发生更改,则不会阻止组件重命名。
如果这看起来是多余的,听起来就像它,但它是必要的,所以这种反应是肯定的,它有最新的状态。像这样运行JS比拥有一些状态内存来检查更改更快,而且对于开发人员来说也更透明(以及VDOM是如何实现的)。
发布于 2022-01-19 10:54:35
预期的产出无法实现。
useEffect在组件挂载时呈现,在每次状态更改时重新呈现(索引)。
const Example = () => {
const [index, setIndex] = React.useState(0)
console.log('Rendering: ', index)
React.useEffect(() => {
console.log('Triggered: ', index)
setIndex(4)
}, [index])
return <h1>{index}</h1>
}输出:
发布于 2022-01-19 10:55:18
useEffect的工作方式只有在呈现页面组件之后才能运行。
希望这能帮助你理解。
第一个渲染索引为0。
Rendering: 0它触发useEffect。
Triggered: 0索引在useEffect中更新,而在组件中没有更新。然后呈现将索引更新为4。
Rendering: 4useEffect运行是因为索引已经更改。
Triggered: 4组件将再次呈现,但索引仍然是4,因此useEffect不会再次运行。
Rendering: 4https://stackoverflow.com/questions/70769126
复制相似问题