在我的React Native应用程序中,如果某个道具已更改,我想触发一个函数。像这样:
componentDidUpdate(prevProps) {
if (prevProps.a !== this.props.a) {
<trigger event>
}
}
问题在于我假设prevProps.a !== this.props.a
总是正确的,因为它是通过引用进行比较的。
解决此问题的最佳方法是什么,以便仅在this.props.a
的属性发生更改时才会触发我的事件?
答案 0 :(得分:0)
最好直接比较属性,而不是像这样比较整个对象:
componentDidUpdate(prevProps) {
if (prevProps.a.field1 === this.props.a.field1) {
// Do stuff here
}
}
但是,如果您仍想比较具有深层嵌套属性的两个对象,执行此操作的一种简单方法是对两个对象进行字符串化,然后直接比较字符串:
if (JSON.stringify(prevProps.a) === JSON.stringify(this.props.a) {
// Do stuff here
}
答案 1 :(得分:0)
这在某种程度上取决于要比较的对象a
的性质。如果是特定属性的问题,那么您显然可以将它们进行单独比较,这将始终是最有效的方法。但是,如果要对a
进行任何更改(包括嵌套对象内部的深层更改)来触发代码,则比较对象的字符串表示形式(JSON.stringify)可以解决问题。但是它也是低效的。一种中间方法是进行浅表比较,下面是一些代码(不少于React团队)来做到这一点:
export function shallowEqual(objA: any, objB: any, compare?, compareContext?) {
let ret = compare ? compare.call(compareContext, objA, objB) : void 0;
if (ret !== void 0) {
return !!ret;
}
if (objA === objB) {
return true;
}
if (typeof objA !== 'object' || !objA || typeof objB !== 'object' || !objB) {
return false;
}
const keysA = Object.keys(objA);
const keysB = Object.keys(objB);
if (keysA.length !== keysB.length) {
return false;
}
const bHasOwnProperty = Object.prototype.hasOwnProperty.bind(objB);
// Test for A's keys different from B.
for (let idx = 0; idx < keysA.length; idx++) {
const key = keysA[idx];
if (!bHasOwnProperty(key)) {
return false;
}
const valueA = objA[key];
const valueB = objB[key];
ret = compare ? compare.call(compareContext, valueA, valueB, key) : void 0;
if (ret === false || (ret === void 0 && valueA !== valueB)) {
return false;
}
}
如果您需要进行有效的深度比较(而不是JSON.stringify),那么最好使用react-fast-compare
(here)之类的库。
(还要注意,JSON.stringify
在某些情况下并不完美,因为日期和函数之类的某些对象未正确或根本没有字符串化。在实践中,这些限制通常在React中不是问题,但您应该至少要意识到它们。)