使用Hooks,如果我使用与 state
相同的值调用 setState
,它会重新渲染组件吗?
如果是,我该如何避免这种情况?
例如:
const [state, setState] = useState(foo)
...
// any where in the code
setState(foo)
考虑到foo
可以是任何东西,比如{}
、true
、props.bar
或者来自组件外部(常量)的变量。
使用Hooks,如果我使用与 state
相同的值调用 setState
,它会重新渲染组件吗?
如果是,我该如何避免这种情况?
例如:
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
的参数,那么它将会重新渲染组件。
这里是一个 代码示例 供您参考。
尝试注释掉 handleClick
方法中的第一个 setState
并取消注释第二个 setState
,以查看差异。
简而言之,如果您的状态是原始值(数字、字符串、布尔值等),那么使用setState hook设置相同的值不会触发重新渲染。 如果您的状态是对象或数组,则行为将有所不同。
https://overreacted.io/how-are-function-components-different-from-classes/
https://dmitripavlutin.com/value-vs-reference-javascript/
useMemo
声明,它都不会触发重新渲染。因此,我们可以简单地说“如果Object.is(prevValue, newValue)
返回true
,它就不会重新渲染”。 - Ricola有点晚了,但我发现一种奇怪的情况,即将状态设置为相同的值会触发两次重新渲染,然后通常会表现出良好的行为。将状态设置为2将触发两次重新渲染。
任何解释?
export default function App() {
const [state, setState] = React.useState(1);
console.log("App rendered");
console.log({ state });
return (
<div className="App">
<button
onClick={() => {
setState(1);
}}
>
update state with same value
</button>
<button
onClick={() => {
setState(2);
}}
>
update state with different value
</button>
<div>state:{state}</div>
</div>
);
}
这是一个与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>
);
}
希望您能阅读这篇文章,它涉及与该主题相关的有用信息:
如果你的更新函数返回与当前状态完全相同的值,则随后的重新渲染将被完全跳过。
https://reactjs.org/docs/hooks-reference.html#functional-updates - Joyce LeesetState({ foo: 'bar' })
这样的字面对象,即使该对象看起来相同,它也会被重新呈现。这是因为每次创建字面对象时,它都被视为与旧对象不同。就像比较两个字面对象{a: 1} === {a: 1}
时返回false
一样。 - Cuong Vu