bel*_*a53 2 javascript reactjs
最近我看到类似于以下人为示例的代码:
const MyComp = props => {
const [prevProps, setPrevProps] = useState(props)
if (props !== prevProps) {
setPrevProps(props);
// do something else...
}
}
Run Code Online (Sandbox Code Playgroud)
该组件使用某种派生状态来记住之前的道具。如果 的内存位置发生props了变化 ( props !== prevProps),它将新的 props 同步到useState。
是的,这没有多大意义,但我的观点是:React 是否做出任何保证,即 的对象引用props保持不变,因为没有包含的属性props已更改?
至少,这似乎是我所做的测试的情况。如果父组件更改了任何道具,则会props创建一个新对象。
我将不胜感激任何证明这一点的官方文档链接。
React 是否保证 props 的对象引用保持不变,因为 props 的包含属性没有改变?
不,它没有。
如果父组件更改了任何道具,则会创建一个新的道具对象。
如果父级重新渲染,子级将始终在新对象中接收其道具,即使其中没有任何更改。
如果要防止这种情况发生,则必须使用
PureComponentorReact.memo将对props对象的所有属性执行浅等比较,并在没有更改的情况下防止重新渲染。
const { memo, useState, useEffect } = React;
const Child = props => {
// only gets called when `props` changes
useEffect(() => console.log(props.name, ": props changed"), [props]);
return <p>{props.name}: {props.text}</p>;
};
const MemoChild = memo(Child);
const Parent = () => {
const [count, setCount] = useState(0);
const [text, setText] = useState("foo");
const handleTextChange = event => setText(event.target.value);
return (
<div>
<button onClick={() => setCount(c => c + 1)}>
Click to force Re-Render
</button>
<input id="text" value={text} onChange={handleTextChange} />
<Child name="Child without memo()" text={text} />
<MemoChild name="Child with memo()" text={text} />
</div>
);
};
ReactDOM.render(<Parent />, document.getElementById('root'))Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>Run Code Online (Sandbox Code Playgroud)
看看这个例子。你会看到,当你按下按钮时,没有使用的孩子memo会重新渲染,即使道具name还是text没有改变。它仍然会收到一个新props对象。
但是当你在 input 中输入一些东西时,两个组件都会重新渲染,因为textprops的属性发生了变化。
还需要注意的是,这只是一种性能优化。您不应memo始终依赖于防止重新渲染。
此方法仅作为性能优化存在。不要依赖它来“阻止”渲染,因为这可能会导致错误。