javascript - attribute - ¿Cómo reacciona el trabajo de comparación superficial en
title css (5)
En esta documentación de React, se dice que
shallowCompare realiza una comprobación de igualdad superficial en los accesorios actuales y los objetos nextProps, así como 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, entonces 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 vamos a anular esto para aumentar el rendimiento.
La comparación superficial funciona comprobando si dos valores son iguales en el caso de tipos primitivos como cadena, números y, en el caso de un objeto, solo verifica la referencia . Entonces, si compara superficialmente un objeto anidado profundo, solo verificará la referencia, no los valores dentro de ese objeto.
El fragmento de igualdad superficial de @supi anterior (
https://.com/a/51343585/800608
) falla si
prevObj
tiene una clave que
newObj
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.
La comparación superficial verifica la igualdad. Al comparar valores escalares (números, cadenas) compara sus valores. Al comparar objetos, no compara sus atributos, solo se comparan sus referencias (por ejemplo, "¿apuntan al mismo objeto?).
Consideremos la siguiente forma del objeto de
user
user = {
name: "John",
surname: "Doe"
}
Ejemplo 1:
const user = this.state.user;
user.name = "Jane";
console.log(user === this.state.user); // true
Observe que cambió el nombre de los usuarios. Incluso con este cambio, los objetos son iguales. Las referencias son exactamente iguales.
Ejemplo 2
const user = clone(this.state.user);
console.log(user === this.state.user); // false
Ahora, sin ningún cambio en las propiedades del objeto, son completamente diferentes. Al clonar el objeto original, crea una nueva copia, con diferente referencia.
La función de clonación podría verse así (sintaxis ES6)
const clone = obj => Object.assign({}, ...obj);
La comparación superficial es una forma eficiente de detectar cambios. Espera que no mutes datos.
También hay una explicación heredada de comparación superficial en React:
shallowCompare realiza una comprobación de igualdad superficial en los accesorios actuales y los objetos nextProps, así como el estado actual y los objetos nextState.
Lo hace iterando sobre las claves de los objetos que se comparan y devolviendo verdadero cuando los valores de una clave en cada objeto no son estrictamente iguales.
UPD : La documentación actual dice sobre la comparación superficial:
Si la función render () de su componente React rinde el mismo resultado con los mismos accesorios y estado, puede usar React.PureComponent para aumentar el rendimiento en algunos casos.
React.PureComponent''s shouldComponentUpdate () solo compara superficialmente los objetos. Si estos contienen estructuras de datos complejas, puede producir falsos negativos para diferencias más profundas. Solo extienda PureComponent cuando espere tener accesorios y estado simples, o use forceUpdate () cuando sepa que las estructuras de datos profundos han cambiado
UPD2: Creo que la Reconciliation también es un tema importante para la comprensión de comparación superficial.
la comparación superficial es cuando las propiedades de los objetos que se comparan se hacen usando "===" o igualdad estricta y no realizarán comparaciones más profundas en las propiedades. por ej.
// 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 que
updated_game_item.teams
.
Para que 2 objetos sean iguales, deben apuntar al mismo objeto.
Por lo tanto, esto da como resultado que el estado sea evaluado para ser actualizado
// 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 del equipo 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 propiedad
updated_game_item3.first_world_cup
falla la evaluación estricta ya que 1930 es un número, mientras que
game_item.first_world_cup
es una cadena.
Si la comparación hubiera sido floja (==) esto habría pasado.
No obstante, esto también dará como resultado una actualización de estado.
Notas adicionales:
- Hacer una comparación profunda no tiene sentido, ya que afectaría significativamente el rendimiento si el objeto de estado está profundamente anidado. Pero si no está demasiado anidado y aún necesita una comparación profunda, impleméntelo en shouldComponentUpdate y verifique si eso es suficiente.
- Definitivamente puede mutar el objeto de estado directamente, pero el estado de los componentes no se vería afectado, ya que está en el flujo del método setState que reacciona implementa los ganchos del ciclo de actualización de componentes. Si actualiza el objeto de estado directamente para evitar deliberadamente los ganchos del ciclo de vida del componente, entonces probablemente debería estar usando una variable u objeto simple para almacenar los datos y no el objeto de estado.