我已经玩了一段时间的React并阅读了文档,发现一个问题让我感到奇怪,为什么在父组件状态改变时,即使子组件的属性相同,React也会重新渲染子元素?
为了防止这种重新渲染,为什么应该将组件包装在Memo()中呢?
是否应该将Memo作为每个React组件的默认选项,或者是否应该对所有组件都使用它呢?
memo 是 PureComponent 在函数组件中的实现。PureComponent 在类组件中执行浅比较,而在函数组件中,你可以使用 memo
、useMemo
(将值进行记忆)以及 useCallback
(将函数进行记忆)。
memo
包装我的组件(回调函数必须在useCallback
中进行包装)。每次父组件重新渲染时,它都会创建一个新的回调函数并将其发送到其子级。子级“看到”一个新函数(因为它是一个不同的对象),并且重新渲染,因为出现了一个新的属性。useCallback
可以缓存回调函数,而memo
可以将您的组件转换为Pure FC,以执行浅比较属性。这里有一个很好的[资源] (https://dmitripavlutin.com/use-react-memo-wisely/)。 - Andrii Lukianenko尝试使用PureComponents,因为在状态改变时React会重新渲染,如果您的父组件重新渲染,则所有子组件也将按相同顺序重新渲染。为了避免重新渲染子组件,您可以使用React.Memo、useMemo或useCallback。虽然不是每次都将组件记忆化。
在每次状态改变时,React都会触发渲染函数,进而调用其子组件进行重新渲染,请参考以下示例来解决您的问题,或访问https://www.robinwieruch.de/react-prevent-rerender-component。
function Parent() {
const [item, setItem] = useState({ name: "item", value: 0 });
const handleChangeItem = useCallback(() => {
setItem(prevItem => ({ ...prevItem, value: prevItem.value + 1 }));
}, []);
return (
<>
Name: {item.name} Value: {item.value}
<Child changeItem={handleChangeItem} />
</>
);
}
const Child = React.memo(function Child({ item, changeItem }) {
function handleClick() {
changeItem();
}
console.log("child render");
return (
<div>
<button onClick={handleClick}>change state in parent</button>
</div>
);
});