una textos texto repitan repetir repeticiones repeticion parrafo para palabras palabra mucho modos las innecesarias evitar ejemplos donde corregir con como reactjs redux immutable.js reselect

reactjs - textos - Cómo evitar las repeticiones de React cuando se usa reselectar para calcular el estado derivado



texto donde se repitan palabras (3)

Resolví mi problema, pero creo que no hay una respuesta correcta, ya que realmente depende de una situación específica. En mi caso, decidí seguir este enfoque:

Uno de los desafíos que el selector original manejó muy bien fue que la información final se compiló a partir de muchas piezas entregadas en un orden arbitrario. Si decidiera acumular la información final en mis reductores de forma incremental, tendría que asegurarme de contar con todos los escenarios posibles (todos los pedidos posibles a los que podrían llegar las piezas de información) y definir las transformaciones entre todos los estados posibles. Mientras que con la reselección, simplemente puedo tomar lo que tengo actualmente y sacar algo de él.

Para mantener esta funcionalidad, decidí mover la lógica del selector a un reductor principal de envoltura .

De acuerdo, digamos que tengo tres reductores, A, B y C, y los selectores correspondientes. Cada uno maneja una pieza de información. La pieza podría cargarse desde el servidor o podría originarse desde el usuario en el lado del cliente. Este sería mi selector original:

const makeFinalState(a, b, c) => (new List(a)).map(item => new MyRecord({ ...item, ...(b[item.id] || {}), ...(c[item.id] || {}) }); export const finalSelector = createSelector( [selectorA, selectorB, selectorC], (a, b, c) => makeFinalState(a, b, c,));

(Este no es el código real, pero espero que tenga sentido. Tenga en cuenta que, independientemente del orden en que estén disponibles los contenidos de los reductores individuales, el selector generará finalmente la salida correcta).

Espero que mi problema esté claro ahora. En caso de que el contenido de cualquiera de esos reductores cambie, el selector se vuelve a calcular desde el principio, generando instancias completamente nuevas de todos los registros que eventualmente resultan en renders completos de los componentes de React.

Mi solución actual parece ligera:

export default function finalReducer(state = new Map(), action) { state = state .update(''a'', a => aReducer(a, action)) .update(''b'', b => bReducer(b, action)) .update(''c'', c => cReducer(c, action)); switch (action.type) { case HEAVY_ACTION_AFFECTING_A: case HEAVY_ACTION_AFFECTING_B: case HEAVY_ACTION_AFFECTING_C: return state.update(''final'', final => (final || new List()).mergeDeep( makeFinalState(state.get(''a''), state.get(''b''), state.get(''c''))); case LIGHT_ACTION_AFFECTING_C: const update = makeSmallIncrementalUpdate(state, action.payload); return state.update(''final'', final => (final || new List()).mergeDeep(update)) } } export const finalSelector = state => state.final;

La idea central es esta:

  • Si sucede algo grande (es decir, obtengo una enorme cantidad de datos del servidor), reconstruyo todo el estado derivado.
  • Si sucede algo pequeño (es decir, los usuarios seleccionan un elemento), solo realizo un cambio incremental rápido, tanto en el reductor original como en el reductor principal de envoltura (hay cierta duplicidad, pero es necesario lograr consistencia y buen rendimiento).

La principal diferencia con la versión del selector es que siempre fusiono el nuevo estado con el anterior. La biblioteca Immutable.js es lo suficientemente inteligente como para no reemplazar las viejas instancias de Record con las nuevas instancias de Record si su contenido es completamente el mismo. Por lo tanto, las instancias originales se conservan y, como resultado, los componentes puros correspondientes no se vuelven a procesar.

Obviamente, la fusión profunda es una operación costosa, por lo que no funcionará para conjuntos de datos realmente grandes. Pero la verdad es que este tipo de operaciones aún es rápido en comparación con las repeticiones y las operaciones DOM. Así que este enfoque puede ser un buen compromiso entre el rendimiento y la legibilidad / concisión del código.

Nota final: si no fuera por esas acciones ligeras manejadas por separado, este enfoque sería esencialmente equivalente a reemplazar el shallowEqual con deepEqual dentro del método shouldComponentUpdate de componentes puros.

Estoy usando la combinación definitiva de React + Redux + Reselect + Immutable.js en mi aplicación. Me gusta la idea de reseleccionar porque me permite mantener mi estado (mantenido por los reductores) lo más simple posible. Utilizo un selector para calcular el estado real que necesito, que luego se alimenta a los componentes React.

El problema aquí es que un pequeño cambio en una vez de los reductores hace que los selectores vuelvan a calcular todo el resultado derivado y, como resultado, también se actualiza toda la UI de React. Mis componentes puros no funcionan. Es lento.

Ejemplo típico: la primera parte de mis datos proviene del servidor y es básicamente inmutable. La segunda parte es mantenida por el cliente y está mutada usando las acciones de reducción. Son mantenidos por reductores separados.

Utilizo un selector para unir ambas partes en una sola lista de Registros que luego se pasa a los componentes Reaccionar. Pero obviamente, cuando cambio una sola cosa en uno de los objetos, toda la lista se regenera y se crean nuevas instancias de Registros. Y la IU se vuelve a renderizar por completo.

Obviamente, ejecutar el selector cada vez no es exactamente eficiente, pero sigue siendo bastante rápido y estaría dispuesto a hacer esa transacción (porque hace que el código sea más simple y más limpio). El problema es la representación real, que es lenta.

Lo que tendría que hacer sería fusionar en profundidad el nuevo resultado del selector con el anterior, porque la biblioteca Immutable.js es lo suficientemente inteligente como para no crear nuevas instancias cuando no se cambió nada. Pero como los selectores son funciones simples que no tienen acceso a productos anteriores, supongo que no es posible.

Supongo que mi enfoque actual es incorrecto y me gustaría escuchar otras ideas.

Probablemente el camino a seguir sería deshacerse de reseleccionar en este caso y mover la lógica a una jerarquía de reductores que usaría actualizaciones incrementales para mantener el estado deseado.


Parece que estás describiendo un escenario muy cercano al por qué escribí re-reselect .

re-reselect es una envoltura de reselect pequeña, que inicializa los selectores sobre la marcha usando una fábrica memorada.

(Descargo de responsabilidad: soy el autor de re-reselect ).


Este tipo de escenario a menudo se puede resolver refacturando cómo la UI está conectada al estado. Supongamos que tiene un componente que muestra una lista de elementos: en lugar de conectarlo a la lista de elementos ya compilada, puede conectarlo a una lista simple de identificadores y conectar cada elemento individual a su registro mediante id. De esta forma, cuando un registro cambia, la lista de identificadores en sí misma no cambia y solo se vuelve a procesar el componente conectado correspondiente.

Si en su caso, si el registro se ensambla desde diferentes partes del estado, el selector que produce registros individuales podría conectarse a las partes relevantes del estado para este registro en particular.

Ahora, sobre el uso de inmutable.js con reselect: esta combinación funciona mejor si las partes sin procesar de su estado ya son objetos inmutable.js. De esta forma, puede aprovechar el hecho de que utilizan estructuras de datos persistentes, y la función de memorización predeterminada de reselect funciona mejor. Siempre puede anular esta función de memorización, pero tiene la sensación de que un selector debe acceder a su valor de retorno anterior si a menudo es un signo de que está a cargo de los datos que deben mantenerse en el estado / o de que está recopilando demasiados datos a la vez, y que tal vez los selectores más granulares podrían ayudar.