mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
Update deepDiffer usage in React Native renderer (#17282)
* Add RN prop diffing test with function values * Update RN deepDiffer mock * Explicitly ignore functions in RN prop differ
This commit is contained in:
@@ -38,7 +38,7 @@ function defaultDiffer(prevProp: mixed, nextProp: mixed): boolean {
|
||||
return true;
|
||||
} else {
|
||||
// For objects and arrays, the default diffing algorithm is a deep compare
|
||||
return deepDiffer(prevProp, nextProp);
|
||||
return deepDiffer(prevProp, nextProp, {unsafelyIgnoreFunctions: true});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,20 +3,43 @@
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// TODO: Move deepDiffer into react
|
||||
type Options = {|+unsafelyIgnoreFunctions?: boolean|};
|
||||
|
||||
const deepDiffer = function(one: any, two: any): boolean {
|
||||
/*
|
||||
* @returns {bool} true if different, false if equal
|
||||
*/
|
||||
const deepDiffer = function(
|
||||
one: any,
|
||||
two: any,
|
||||
maxDepthOrOptions: Options | number = -1,
|
||||
maybeOptions?: Options,
|
||||
): boolean {
|
||||
const options =
|
||||
typeof maxDepthOrOptions === 'number' ? maybeOptions : maxDepthOrOptions;
|
||||
const maxDepth =
|
||||
typeof maxDepthOrOptions === 'number' ? maxDepthOrOptions : -1;
|
||||
if (maxDepth === 0) {
|
||||
return true;
|
||||
}
|
||||
if (one === two) {
|
||||
// Short circuit on identical object references instead of traversing them.
|
||||
return false;
|
||||
}
|
||||
if (typeof one === 'function' && typeof two === 'function') {
|
||||
// We consider all functions equal
|
||||
return false;
|
||||
// We consider all functions equal unless explicitly configured otherwise
|
||||
let unsafelyIgnoreFunctions =
|
||||
options == null ? null : options.unsafelyIgnoreFunctions;
|
||||
if (unsafelyIgnoreFunctions == null) {
|
||||
unsafelyIgnoreFunctions = true;
|
||||
}
|
||||
return !unsafelyIgnoreFunctions;
|
||||
}
|
||||
if (typeof one !== 'object' || one === null) {
|
||||
// Primitives can be directly compared
|
||||
@@ -37,13 +60,13 @@ const deepDiffer = function(one: any, two: any): boolean {
|
||||
return true;
|
||||
}
|
||||
for (let ii = 0; ii < len; ii++) {
|
||||
if (deepDiffer(one[ii], two[ii])) {
|
||||
if (deepDiffer(one[ii], two[ii], maxDepth - 1, options)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const key in one) {
|
||||
if (deepDiffer(one[key], two[key])) {
|
||||
if (deepDiffer(one[key], two[key], maxDepth - 1, options)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,4 +231,44 @@ describe('ReactNativeAttributePayload', () => {
|
||||
),
|
||||
).toEqual({a: null, c: true});
|
||||
});
|
||||
|
||||
it('should skip changed functions', () => {
|
||||
expect(
|
||||
diff(
|
||||
{
|
||||
a: function() {
|
||||
return 1;
|
||||
},
|
||||
},
|
||||
{
|
||||
a: function() {
|
||||
return 9;
|
||||
},
|
||||
},
|
||||
{a: true},
|
||||
),
|
||||
).toEqual(null);
|
||||
});
|
||||
|
||||
it('should skip deeply-nested changed functions', () => {
|
||||
expect(
|
||||
diff(
|
||||
{
|
||||
wrapper: {
|
||||
a: function() {
|
||||
return 1;
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
wrapper: {
|
||||
a: function() {
|
||||
return 9;
|
||||
},
|
||||
},
|
||||
},
|
||||
{wrapper: true},
|
||||
),
|
||||
).toEqual(null);
|
||||
});
|
||||
});
|
||||
|
||||
14
scripts/flow/react-native-host-hooks.js
vendored
14
scripts/flow/react-native-host-hooks.js
vendored
@@ -19,8 +19,20 @@ import type {
|
||||
import type {RNTopLevelEventType} from 'legacy-events/TopLevelEventTypes';
|
||||
import type {CapturedError} from 'react-reconciler/src/ReactCapturedValue';
|
||||
|
||||
type DeepDifferOptions = {|+unsafelyIgnoreFunctions?: boolean|};
|
||||
|
||||
declare module 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface' {
|
||||
declare export function deepDiffer(one: any, two: any): boolean;
|
||||
declare export function deepDiffer(
|
||||
one: any,
|
||||
two: any,
|
||||
maxDepth?: number,
|
||||
options?: DeepDifferOptions,
|
||||
): boolean;
|
||||
declare export function deepDiffer(
|
||||
one: any,
|
||||
two: any,
|
||||
options: DeepDifferOptions,
|
||||
): boolean;
|
||||
declare export function deepFreezeAndThrowOnMutationInDev<T>(obj: T): T;
|
||||
declare export function flattenStyle(style: any): any;
|
||||
declare export var RCTEventEmitter: {
|
||||
|
||||
Reference in New Issue
Block a user