我最近一直在学习React 16.8的新功能。这个问题可能很愚蠢。我天真地认为,React的Pure Component应该自动避免不必要的重新渲染操作。
在以下示例中,App
本身是无状态组件。我使用useState
来维护两个状态对象text
和nested: {text}
。
有3个测试。前两个测试有效。无论有多少次,我都会更改状态,无需进行任何重新渲染操作。
现在,第三个测试尝试使用相同的字符串值设置text
的状态,但是引用不同。我希望没有任何东西可以重新渲染,但是实际上<Headline/>
将被重新渲染。
我应该使用某种记忆技巧来避免吗?我觉得将其存档将太多代码。并且程序员必须非常小心地编写高质量的React代码。 ..
class Headline extends React.PureComponent {
render() {
const {text} = this.props;
return <h1>{text} (render time: {Date.now()})</h1>;
}
}
const simpleText = 'hello world'
const App = () => {
const [text, setText] = React.useState(simpleText)
const [nested, setNested] = React.useState({text: simpleText})
return (
<div>
<Headline text={text}/>
<Headline text={nested.text}/>
<button onClick={()=>setText(simpleText)}>
test 1: the first line should not change (expected)
</button>
<button onClick={()=>setNested({text: simpleText})}>
test 2: the second line will not change (expected)
</button>
<button onClick={()=>setText(new String(simpleText))}>
test 3: the first line will change on every click (why?)
</button>
</div>
)
}
ReactDOM.render(<App />, document.querySelector("#app"))
这是jsfiddle中的一个现场游乐场:
https://jsfiddle.net/fL0psxwo/1/
谢谢大家的反应,欢呼!
更新1: 感谢丹尼斯提及why-did-you-render
作者指出了一些非常有用的文章。我认为这对每个人都是很有教育意义的。 https://medium.com/welldone-software/why-did-you-render-mr-big-pure-react-component-part-2-common-fixing-scenarios-667bfdec2e0f
更新2:
我创建了一个名为withDirtyCheck
的新钩子,以便我的代码将自动进行内容脏检查。
import isEqual from 'lodash-es/isEqual';
export const withDirtyCheck = ([getter, setter]) => {
const setStateIfDirty = (nextState) =>
setter((prevState) => (isEqual(prevState, nextState) ? prevState : nextState));
return [getter, setStateIfDirty];
};
答案 0 :(得分:3)
问题在于,使用new
operator创建的String Object
总是不同于先前的状态。
'hello world' === new String('hello world') // false, always.
'hello world' === String('hello world') // true
选中此example:
setText(prevState => {
// Will render
// const currState = new String(simpleText);
// Won't render
const currState = String(simpleText);
console.log(prevState === currState); // if true, no re-render
// if false, re-render
return currState;
});
请参阅What is the difference between string primitives and String objects in JavaScript?