En esta documentación de React, se dice que
shallowCompare realiza una verificación de igualdad superficial en los objetos de utilería actuales y nextProps, así como en el estado actual y los objetos nextState.
Lo que no puedo entender es que si compara superficialmente los objetos, el método shouldComponentUpdate siempre devolverá verdadero, como
No debemos mutar los estados.
y si no estamos mutando los estados, la comparación siempre devolverá falso y, por lo tanto, la actualización shouldComponent siempre devolverá verdadero. Estoy confundido acerca de cómo está funcionando y cómo anularemos esto para mejorar el rendimiento.
fuente
La comparación superficial es cuando las propiedades de los objetos que se comparan se realizan utilizando "===" o igualdad estricta y no realizarán comparaciones más profundas en las propiedades. por ejemplo
// a simple implementation of the shallowCompare. // only compares the first level properties and hence shallow. // state updates(theoretically) if this function returns true. function shallowCompare(newObj, prevObj){ for (key in newObj){ if(newObj[key] !== prevObj[key]) return true; } return false; } // var game_item = { game: "football", first_world_cup: "1930", teams: { North_America: 1, South_America: 4, Europe: 8 } } // Case 1: // if this be the object passed to setState var updated_game_item1 = { game: "football", first_world_cup: "1930", teams: { North_America: 1, South_America: 4, Europe: 8 } } shallowCompare(updated_game_item1, game_item); // true - meaning the state // will update.
Aunque ambos objetos parecen ser iguales,
game_item.teams
no es la misma referencia queupdated_game_item.teams
. Para que dos objetos sean iguales, deben apuntar al mismo objeto. Por lo tanto, esto da como resultado que el estado se evalúe para actualizarse// Case 2: // if this be the object passed to setState var updated_game_item2 = { game: "football", first_world_cup: "1930", teams: game_item.teams } shallowCompare(updated_game_item2, game_item); // false - meaning the state // will not update.
Esta vez, cada una de las propiedades devuelve verdadero para la comparación estricta, ya que la propiedad de teams en el objeto nuevo y antiguo apunta al mismo objeto.
// Case 3: // if this be the object passed to setState var updated_game_item3 = { first_world_cup: 1930 } shallowCompare(updated_game_item3, game_item); // true - will update
La
updated_game_item3.first_world_cup
propiedad no pasa la evaluación estricta ya que 1930 es un número mientras quegame_item.first_world_cup
es una cadena. Si la comparación hubiera sido floja (==), esto habría pasado. No obstante, esto también resultará en una actualización del estado.Notas adicionales:
fuente
prevObj
contiene una clave quenewObj
no tiene, la comparación fallará.fuente
También hay una explicación heredada de la comparación superficial en React:
UPD : la documentación actual dice acerca de la comparación superficial:
UPD2: Creo que la reconciliación también es un tema importante para la comprensión comparativa superficial.
fuente
and returning true when the values
El fragmento igual superficial de @supi anterior ( https://stackoverflow.com/a/51343585/800608 ) falla si
prevObj
tiene una clave quenewObj
no tiene. Aquí hay una implementación que debería tener eso en cuenta:const shallowEqual = (objA, objB) => { if (!objA || !objB) { return objA === objB } return !Boolean( Object .keys(Object.assign({}, objA, objB)) .find((key) => objA[key] !== objB[key]) ) }
Tenga en cuenta que lo anterior no funciona en Explorer sin polyfills.
fuente
Hay una implementación con ejemplos.
const isObject = value => typeof value === 'object' && value !== null; const compareObjects = (A, B) => { const keysA = Object.keys(A); const keysB = Object.keys(B); if (keysA.length !== keysB.length) { return false; } return !keysA.some(key => !B.hasOwnProperty(key) || A[key] !== B[key]); }; const shallowEqual = (A, B) => { if (A === B) { return true; } if ([A, B].every(Number.isNaN)) { return true; } if (![A, B].every(isObject)) { return false; } return compareObjects(A, B); }; const a = { field: 1 }; const b = { field: 2 }; const c = { field: { field: 1 } }; const d = { field: { field: 1 } }; console.log(shallowEqual(1, 1)); // true console.log(shallowEqual(1, 2)); // false console.log(shallowEqual(null, null)); // true console.log(shallowEqual(NaN, NaN)); // true console.log(shallowEqual([], [])); // true console.log(shallowEqual([1], [2])); // false console.log(shallowEqual({}, {})); // true console.log(shallowEqual({}, a)); // false console.log(shallowEqual(a, b)); // false console.log(shallowEqual(a, c)); // false console.log(shallowEqual(c, d)); // false
fuente