¿No es Redux un estado global glorificado?

84

Entonces comencé a aprender React hace una semana e inevitablemente llegué al problema del estado y cómo se supone que los componentes se comunican con el resto de la aplicación. Busqué y Redux parece ser el sabor del mes. Leí toda la documentación y creo que en realidad es una idea bastante revolucionaria. Aquí están mis pensamientos al respecto:

En general, se acepta que el estado es bastante malo y una gran fuente de errores de programación. En lugar de esparcirlo por toda la aplicación, Redux dice ¿por qué no tenerlo todo concentrado en un árbol de estado global que debe emitir acciones para cambiar? Suena interesante. Todos los programas necesitan un estado, así que guardémoslo en un espacio impuro y modifiquémoslo solo desde allí para que los errores sean fáciles de localizar. Luego, también podemos vincular declarativamente piezas de estado individuales a componentes de React y hacer que se redibujen automáticamente y todo es hermoso.

Sin embargo, tengo dos preguntas sobre todo este diseño. Por un lado, ¿por qué es necesario que el árbol estatal sea inmutable? Digamos que no me importa la depuración de viajes en el tiempo, la recarga en caliente y ya he implementado deshacer / rehacer en mi aplicación. Parece tan engorroso tener que hacer esto:

case COMPLETE_TODO:
  return [
    ...state.slice(0, action.index),
    Object.assign({}, state[action.index], {
      completed: true
    }),
    ...state.slice(action.index + 1)
  ];

En lugar de esto:

case COMPLETE_TODO:
  state[action.index].completed = true;

Sin mencionar que estoy haciendo una pizarra en línea solo para aprender y cada cambio de estado puede ser tan simple como agregar un trazo de pincel a la lista de comandos. Después de un tiempo (cientos de pinceladas), la duplicación de toda esta matriz podría comenzar a ser extremadamente costosa y requerir mucho tiempo.

Estoy de acuerdo con un árbol de estado global que es independiente de la interfaz de usuario que se muta a través de acciones, pero ¿realmente necesita ser inmutable? ¿Qué hay de malo en una implementación simple como esta (un borrador muy preliminar escrito en 1 minuto)?

var store = { items: [] };

export function getState() {
  return store;
}

export function addTodo(text) {
  store.items.push({ "text": text, "completed", false});
}

export function completeTodo(index) {
  store.items[index].completed = true;
}

Sigue siendo un árbol de estado global mutado a través de acciones emitidas, pero extremadamente simple y eficiente.

Ryan Peschel
fuente
2
"Por un lado, ¿por qué el árbol del estado necesita ser inmutable?" --- entonces debe proporcionar un algoritmo para determinar si los datos han cambiado. No es posible implementarlo para una estructura de datos arbitraria (si es mutable). Tomar immutablejsy utilizar return state.setIn([action.index, 'completed'], true);para reducir la repetición.
zerkms
1
PD:return state.map(i => i.index == action.index ? {...i, completed: true} : i);
zerkms

Respuestas:

52

¿No es Redux un estado global glorificado?

Por supuesto que es. Pero lo mismo se aplica a todas las bases de datos que haya utilizado. Es mejor tratar a Redux como una base de datos en memoria, de la que sus componentes pueden depender reactivamente.

La inmutabilidad permite verificar si algún subárbol ha sido alterado de manera muy eficiente porque se simplifica a una verificación de identidad.

Sí, su implementación es eficiente, pero todo el dom virtual tendrá que volver a renderizarse cada vez que se manipule el árbol de alguna manera.

Si está utilizando React, eventualmente hará una diferencia con el dom real y realizará manipulaciones mínimas optimizadas por lotes, pero la re-renderización completa de arriba hacia abajo sigue siendo ineficiente.

Para un árbol inmutable, los componentes sin estado solo tienen que verificar si el (los) subárbol (s) de los que depende, difieren en identidades en comparación con los valores anteriores y, de ser así, la representación se puede evitar por completo.

Lorefnon
fuente
3
¿No es esto una optimización prematura? Además, ¿cómo sabemos que el costo de duplicar constantemente objetos inmutables es menor que volver a renderizar el DOM (tampoco el DOM virtual de React mitigaría en gran medida este costo?)
Ryan Peschel
3
Bueno, las bibliotecas GUI de este tipo de optimización durante mucho tiempo (consulte: bitquabit.com/post/the-more-things-change ) Además, la gestión de una estructura de datos inmutable no es tan costosa como podría pensar, por ejemplo, si un nodo cambia, solo es necesario encadenar una única cadena de padres; el resto de los nodos no se ven afectados. Por lo tanto, no duplicamos la estructura de datos completa para cada acción; reutilizamos los subcomponentes que no han cambiado para construir una nueva estructura de datos.
Lorefnon
4
También Reacts Virtual DOM no es exactamente magia oscura - Citando los documentos de React: "Generar el número mínimo de operaciones para transformar un árbol en otro es un problema complejo y bien estudiado - Los algoritmos de última generación tienen una complejidad en el orden de O (n3) donde n es el número de nodos en el árbol ".
lorefnon
2
La razón por la que React puede funcionar mucho mejor en la práctica es porque: React se basa en la heurística, por lo que: "Si no proporciona claves estables (utilizando Math.random () por ejemplo), todos los subárboles van a volver a renderizarse cada vez. Al dar a los usuarios la opción de elegir la clave, tienen la capacidad de dispararse a sí mismos en el pie ". Así como puedes ayudar a React proporcionando claves estables, de la misma manera puedes ayudar a React proporcionando apoyos de datos inmutables.
Lorefnon
1
Con respecto a su matriz de trazos de pincel, consulte: facebook.github.io/immutable-js/docs/#/List Citando de documentos: Las listas están ordenadas por colecciones densas indexadas, al igual que una matriz de JavaScript. Las listas implementan Deque, con adición y eliminación eficientes tanto desde el final (empujar, hacer estallar) como desde el principio (unshift, shift).
Lorefnon