使用钩子,如果我setState使用与 相同的值调用state,它会重新渲染组件吗?
如果是,我怎样才能避免这种情况?
例如
const [state, setState] = useState(foo)
...
// any where in the code
setState(foo)
考虑到foo可以是任何事物,比如{},true,props.bar或从所述部件(常数)的出侧可变。
使用钩子,如果我setState使用与 相同的值调用state,它会重新渲染组件吗?
如果是,我怎样才能避免这种情况?
例如
const [state, setState] = useState(foo)
...
// any where in the code
setState(foo)
考虑到foo可以是任何事物,比如{},true,props.bar或从所述部件(常数)的出侧可变。
如果您setState使用相同的值调用,它不会重新渲染组件。
试试这个:
import React, { useState, useEffect } from "react";
const foo = { foo: 'bar' };
export default ({ name }) => {
const [state, setState] = useState(foo);
console.log("rendered!");
useEffect(() => {
setState(foo);
console.log("state reset!");
});
const handleClick = () => {
console.log("handleClick!");
setState(foo);
// setState({ ...foo, bar : 'baz' });
}
return (<div>
<h1>Hello {name}!</h1>
<button onClick={handleClick}>Click Me</button>
</div>);
};
您会注意到,即使单击该按钮,该值也没有改变。它不是重新渲染组件。如果您更改您调用的参数,setState它将重新渲染组件。
这是您参考的代码示例。
尝试在方法中注释第一个setState并取消注释第二个handleClick以查看差异。
这是一个与 js 语法相关的问题,就像===操作一样。
let times = 0
const init = {name: 'Bob'}
function App() {
const [state, setState] = useState(init)
function modify() {
setState({name: 'Bob'})
}
function modify2() {
setState(init)
}
times ++
return (
<div className="App">
<p>{ times }</p>
<button onClick={modify}>Same Value Will Rerender</button>
<button onClick={modify2}>Same Reference Never Rerender</button>
</div>
);
}
这是一个代码沙盒
您可以重写包装方法:
let times = 0
const init = {name: 'Bob'}
function App() {
const [state, setState] = useState(init)
function modify3() {
setState2({ name: 'Bob' })
}
function setState2(value) {
if (value.name === state.name) {
return
}
setState(value)
}
times ++
return (
<div className="App">
<p>{ times }</p>
<button onClick={modify3}>Same Value Will Not Rerender Yet</button>
</div>
);
}
总结一下
如果您的状态是原始值(数字、字符串、布尔值、...),则使用 setState 钩子设置相同的值不会触发 rerender。如果您的状态是一个对象或数组,那么它的行为会有所不同。
https://overreacted.io/how-are-function-components-different-from-classes/
https://dmittripavlutin.com/value-vs-reference-javascript/