最近我看到了类似于以下人工示例的代码:
const MyComp = props => {
const [prevProps, setPrevProps] = useState(props)
if (props !== prevProps) {
setPrevProps(props);
// do something else...
}
}
该组件使用某种派生状态来记住以前的道具。如果props
的内存位置发生了变化(props !== prevProps
(,它将把新道具同步到useState
。
是的,这没有那么大意义,但我的观点是:React是否保证props
的对象引用保持不变,因为props
的包含属性没有改变?
至少,我所做的测试似乎就是这样。如果父组件更改了任何道具,将创建一个新的props
对象。
如果有任何官方文件链接证明这一点,我将不胜感激。
React是否保证道具的对象引用保持不变,前提是道具的包含属性没有改变?
不,不是
如果父组件更改了任何道具,将创建一个新的道具对象。
如果父对象重新渲染,子对象将始终在新对象中接收其道具,即使其中没有任何更改。
如果你想防止这种情况发生,你必须使用CCD_ 7或CCD_ 8,其将对CCD_。
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'))
<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>
看看这个例子。您将看到,当您按下按钮时,未使用memo
的子级将重新渲染,即使道具name
或text
没有更改。它仍将接收一个新的props
对象。
但是,当您在输入中输入一些内容时,两个组件都会重新渲染,因为道具的text
属性发生了更改。
还应该注意的是,这只是一个性能优化。不应始终依赖memo
来阻止重新渲染。
此方法仅作为性能优化存在。不要依赖它可以"阻止"渲染,因为这可能会导致错误。