为了更深入地了解React.Memo(),我做了一个例子。
我试图将字符串从parent
传递到child
。然后,除了第一个默认渲染外,组件不会被渲染。
但是当我将array
从parent
传递到child
时,组件会重新渲染。
那么为什么组件在传递arrays
和objects
时保持重新渲染,而在传递string
时不重新渲染呢?
是否与javascript
的reference values
和primitive values
有关?
下面是我要做的代码。
parent
:
import Child from "./Child";
export default function App() {
const name = {
firstName: "Amr"
};
return <Child name={name} />;
}
Child
import React from "react";
const Child = ({ name }) => {
const name1 = "Amr";
const name2 = "Amr";
// console.log(name1 === name2);
const obj1 = {
name: "Mohamed"
};
const obj2 = {
name: "Mohamed"
};
const arr1 = ["Amr"];
const arr2 = ["Amr"];
console.log(arr1 === arr2);
// console.log(obj1 === obj2); => obj1 => refrence number 1
// obj2 => refrence number 2
// 1 === 2;
// false
areEqual(name, {
firstName: "Amr"
});
return <h2>{name.firstName}</h2>;
};
// javascript [] {} => refrence value
// javascript '' or anythinng primtive value;
// obj1 = 1, obj2 = 2;
// obj1 === obj2 result false 1 === 2
function areEqual(prevProps, nextPops) {
if (prevProps === nextPops) {
console.log("equal");
} else {
console.log("not equal");
}
}
export default React.memo(Child, areEqual);
我还使用了一个函数areEqual
,它根据prevProps
和nextProps
是否相等返回true
或false
。
当我传递一个String
时,这个函数已经为我返回true
,当我传递一个array
时,这个函数已经返回false
。
所以,我是对的还是少了什么。
感谢更新:
如果我提到的是正确的,那么React.memo()
将是无用的。
是这样吗?
默认情况下,React.memo()
会对道具和道具的对象进行浅层比较——这就是为什么当道具为'object'类型时你会遇到渲染,因为引用在每个渲染上都重新创建。
React.memo
接收两个参数(第二个是可选的),第二个是自定义的相等函数,你可以使用它来稳定渲染时,有道具作为非原语值。例如,你可以这样做:React.memo(SomeComponent, (prevProps, currentProps) => isDeepEqual(prevProps.someObject, currentProps.someObject))
.
意味着React.memo
不是无用的,它只是默认情况下使用浅比较,但也为您提供了提供自定义相等检查器的可能性,您可能想要在示例中使用。要么在React中使用深度平等检查。或者,你应该通过用useMemo包装它们的值来稳定父组件中的props。
这取决于它们的父组件,有时是必要的React.memo但在你的例子中,就像你说的,每次你定义一个数组或对象时,它的引用都会改变。我建议你使用React.useMemo。例如:
const user = React.useMemo(() => {
return {
firstName: "Amr"
}
}, []); // Second parameter works same as useCallback
反应。memo不会重新渲染组件,因为user
道具没有改变