与基于 class 的方法相比,使用 Hooks 设置状态后重新渲染有何不同?
What are the differences when re-rendering after state was set with Hooks compared to the class-based approach?
Class 组件
在 React class 组件中,我们被告知 setState
总是 导致重新渲染,无论状态是否实际更改为一个新的价值。实际上,组件 将 重新渲染,当状态更新为 与之前相同的 值时。
Docs (setState API Reference):
setState() will always lead to a re-render unless
shouldComponentUpdate() returns false.
Hooks(函数组件)
然而,使用钩子时,文档指定将状态更新为与先前状态相同的值,不会导致(子组件)重新渲染:
Docs (useState API Reference):
Bailing out of a state update
If you update a State Hook to the same value as the current state,
React will bail out without rendering the children or firing effects.
(React uses the Object.is comparison algorithm.)
密切相关的问题
- class 组件中的
this.setState
总是导致重新渲染是否正确,即使新的 state
值与之前的值相同?
- 在 函数组件 中使用钩子是否正确,
useState
中的 setState
仅在 state
值时才导致重新渲染与之前的值不同?
- 在class组件的
render
方法中用this.setState
设置state
,与设置state
在 带有钩子的函数组件的函数体内 ?
- 以下说法正确吗?
- 在class组件中,如果我们在
render
方法中设置state
,将会发生无限循环。这是因为 class 组件 并不关心新的 state
是否与之前的 state
相同。它只是在每个 this.setState
. 上不断重新渲染
- 在带有钩子的 函数组件中 但是,在函数体内设置
state
(它在重新渲染时运行类似于 render
方法class components) 会 not 是个问题,因为 function component 刚刚退出当它发现 state
与之前的 state
. 相同时重新渲染
Is it correct that this.setState in class components always cause a
re-render, even when the new state value is identical to the previous?
如果您在 setState 中设置了一个有效值而不是返回 null,除非您的组件是 PureComponent 或者您实现了 shouldComponentUpdate
Is it correct that in function components with hooks, setState from
useState only causes a re-render if the state value is different from
the previous value?
对于使用 useState
挂钩的功能组件,如果以相同状态调用 setter 将不会触发重新渲染。但是,对于偶尔的情况,如果 setter 被立即调用,它确实会导致两次渲染而不是一次
Is setting state with this.setState inside the render method of a
class component, the same as setting state inside the function body of
a function component with hooks?
技术上是的,如果 class 组件导致无限循环,直接在渲染方法中设置状态将导致函数触发重新渲染,如果状态值不同,功能组件就是这种情况.不管怎样,它仍然会导致问题,因为任何其他状态更新都将由于功能组件直接调用状态更新而被还原
In a class component, if we set state in the render method an infinite
loop will occur. This is because the class component does not care
that the new state is the same as the previous state. It just keeps
re-rendering on every this.setState.
是的,因此建议不要在 render 中直接调用 setState
In a function component with hooks however, setting state inside the
function body (which runs at re-render similarly to the render method
in class components) would not be an issue, because the function
component just bails out of re-renders when it sees that the state is
identical to the previous state.
不是 100% 正确,因为您可以使用以前的值触发状态更新,这样以前的值和当前值不是 same.For 示例
setCount(count => count + 1);
在这种情况下,你的组件仍然会陷入死循环
这不是对 OP 的直接回答,但对某些刚接触 React and/or Hooks 并在其副作用和渲染时间上苦苦挣扎的人来说可能有所帮助。
因为这里还没有提到:在功能组件中而不是使用前面提到的(参见已接受答案的评论)ShouldComponentUpdate()
函数,它仅适用于基于 class 的组件,您将使用 useEffect()
挂钩。有了它,您可以告诉您的组件何时 运行 副作用以及在什么条件下,例如当某些依赖项发生变化时。
在 React 文档的这个例子中,只有当 props.source
改变时,函数才会被执行。
useEffect(
() => {
const subscription = props.source.subscribe();
return () => {
subscription.unsubscribe();
};
},
[props.source],
);
Class 组件
在 React class 组件中,我们被告知 setState
总是 导致重新渲染,无论状态是否实际更改为一个新的价值。实际上,组件 将 重新渲染,当状态更新为 与之前相同的 值时。
Docs (setState API Reference):
setState() will always lead to a re-render unless shouldComponentUpdate() returns false.
Hooks(函数组件)
然而,使用钩子时,文档指定将状态更新为与先前状态相同的值,不会导致(子组件)重新渲染:
Docs (useState API Reference):
Bailing out of a state update
If you update a State Hook to the same value as the current state, React will bail out without rendering the children or firing effects. (React uses the Object.is comparison algorithm.)
密切相关的问题
- class 组件中的
this.setState
总是导致重新渲染是否正确,即使新的state
值与之前的值相同? - 在 函数组件 中使用钩子是否正确,
useState
中的setState
仅在state
值时才导致重新渲染与之前的值不同? - 在class组件的
render
方法中用this.setState
设置state
,与设置state
在 带有钩子的函数组件的函数体内 ? - 以下说法正确吗?
- 在class组件中,如果我们在
render
方法中设置state
,将会发生无限循环。这是因为 class 组件 并不关心新的state
是否与之前的state
相同。它只是在每个this.setState
. 上不断重新渲染
- 在带有钩子的 函数组件中 但是,在函数体内设置
state
(它在重新渲染时运行类似于render
方法class components) 会 not 是个问题,因为 function component 刚刚退出当它发现state
与之前的state
. 相同时重新渲染
- 在class组件中,如果我们在
Is it correct that this.setState in class components always cause a re-render, even when the new state value is identical to the previous?
如果您在 setState 中设置了一个有效值而不是返回 null,除非您的组件是 PureComponent 或者您实现了 shouldComponentUpdate
Is it correct that in function components with hooks, setState from useState only causes a re-render if the state value is different from the previous value?
对于使用 useState
挂钩的功能组件,如果以相同状态调用 setter 将不会触发重新渲染。但是,对于偶尔的情况,如果 setter 被立即调用,它确实会导致两次渲染而不是一次
Is setting state with this.setState inside the render method of a class component, the same as setting state inside the function body of a function component with hooks?
技术上是的,如果 class 组件导致无限循环,直接在渲染方法中设置状态将导致函数触发重新渲染,如果状态值不同,功能组件就是这种情况.不管怎样,它仍然会导致问题,因为任何其他状态更新都将由于功能组件直接调用状态更新而被还原
In a class component, if we set state in the render method an infinite loop will occur. This is because the class component does not care that the new state is the same as the previous state. It just keeps re-rendering on every this.setState.
是的,因此建议不要在 render 中直接调用 setState
In a function component with hooks however, setting state inside the function body (which runs at re-render similarly to the render method in class components) would not be an issue, because the function component just bails out of re-renders when it sees that the state is identical to the previous state.
不是 100% 正确,因为您可以使用以前的值触发状态更新,这样以前的值和当前值不是 same.For 示例
setCount(count => count + 1);
在这种情况下,你的组件仍然会陷入死循环
这不是对 OP 的直接回答,但对某些刚接触 React and/or Hooks 并在其副作用和渲染时间上苦苦挣扎的人来说可能有所帮助。
因为这里还没有提到:在功能组件中而不是使用前面提到的(参见已接受答案的评论)ShouldComponentUpdate()
函数,它仅适用于基于 class 的组件,您将使用 useEffect()
挂钩。有了它,您可以告诉您的组件何时 运行 副作用以及在什么条件下,例如当某些依赖项发生变化时。
在 React 文档的这个例子中,只有当 props.source
改变时,函数才会被执行。
useEffect(
() => {
const subscription = props.source.subscribe();
return () => {
subscription.unsubscribe();
};
},
[props.source],
);