我正在使用以下虚拟组件进行一些测验,在执行时(在控制台中)我得到以下结果:
Rendering: 0
Triggered: 0
Rendering: 4
Triggered: 4
Rendering: 4
我很难理解为什么。
第一次渲染:
- 设定
index
为0
。 - 运行 useEffect
undefined
不是0
- useEffect 请求设定
index
为4
第二次渲染:
index
是4
- 为什么useEffect body又被执行了?
第三次渲染:
- 为什么会有重新渲染?
我期望的是:
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>
uj5u.com热心网友回复:
重新渲染的数量实际上是正确的。让我们分析一下会发生什么:
- 渲染 0 - 这是在安装第一次渲染时(在这种状态下,每个
useEffect
都自动运行)
- 触发 0 - 这是初始触发
useEffect
- 渲染 4 - 此重新渲染是因为您将新状态设定
index
为4
- 触发 4 - 这是因为您
index
从 0 更改为 4而触发
- 渲染 4 - 这是因为状态从
4
to更改为运行4
(即使值相同,它也会触发组件重新渲染,因为 React 不知道您是否设定了相同的状态,它需要再次运行)。在此重新渲染中, useEffect未运行,因为index
再次为 4。
基本原理
如果组件在任何时候发生任何变化,例如useState
useContext
, customHook
,则该组件将需要重新渲染。如果父组件重新渲染也会发生这种情况,即使您的组件没有任何更改,子组件也会重新渲染。
其他重新渲染提示和信息
为了防止父组件发生不必要的子组件重新渲染,您可以使用React.memo,如果 props 更改,这将重新渲染您的组件,但不会阻止您的组件在 state 或上述任何钩子发生更改时重新渲染。
如果这看起来是多余的,听起来很像,但有必要让 react 确保它具有最新状态。像这样运行 JS 比拥有一些检查更改的状态存储器要快,而且它对开发人员更透明(以及VDOM的创建方式)
uj5u.com热心网友回复:
无法达到预期的输出。
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>
}
输出:
- 渲染:0 => 组件第一次挂载时,该时间索引为 0
- 触发:0 => 挂载 useEffect 触发,状态更新(0 到 4)
- 渲染:4 => 组件重新渲染,因为状态已从(0 变为 4)
- 已触发:4 => useEffect 重新触发,因为状态已更改(0 到 4)
- 渲染:4 => Componet 重新渲染,因为要检查状态是否已更改(4 到 4,确认没有任何变化)
uj5u.com热心网友回复:
useEffect 的作业方式是它只在页面组件渲染后运行。
希望这能帮助你理解。
第一个渲染索引为 0。
Rendering: 0
它触发了useEffect。
Triggered: 0
索引在 useEffect 中更新,但不在组件中。然后 render 将索引更新为 4。
Rendering: 4
useEffect 运行,因为索引已更改。
Triggered: 4
组件再次渲染,但索引仍为 4,因此 useEffect 不会再次运行。
Rendering: 4
0 评论