javascript - gta - ¿Un almacén de acciones para actualizaciones optimistas es un buen enfoque en Redux/Flux?
redux vs mobx (1)
A los futuros lectores que podrían estar un poco desconcertados: ya no llamamos a estas funciones "tiendas": les llamamos reducers . Así que la pregunta es sobre un reductor recordando acciones .
Personalmente no me gusta el enfoque que estás sugiriendo allí. Estás poniendo la lógica en acciones y usando la herencia para esto. Por el contrario, Redux prescribe acciones para que sean objetos simples sin lógica. No deben "saber" cómo actualizar algún estado, y no deben mantenerlo, sino que deben describir lo que sucedió.
Creo que el enfoque para implementar actualizaciones optimistas en Redux es similar a la forma en que implementaría Deshacer en Redux , que a su vez está inspirado en la arquitectura Elm . La idea es que debe escribir una función que tome un reductor (y algunas opciones) y devuelva un reductor:
function optimistic(reducer) {
return function (state, action) {
// do something?
return reducer(state, action);
}
}
Lo usarías como un reductor normal:
export default combineReducers({
something: optimistic(something) // wrap "something" reducer
})
En este momento solo pasa el estado y la acción al reducer
que envuelve, pero también puede "recordar" las acciones:
function optimistic(reducer) {
return function (state = { history: [] }, action) {
// do something with history?
return {
history: [...state.history, action],
present: reducer(state.history[state.history.length - 1], action)
};
}
}
Ahora acumula todas las acciones en el campo de history
.
Nuevamente, esto por sí mismo no es muy útil, pero probablemente pueda ver cómo puede implementar un reductor de orden superior que:
- realiza un seguimiento de las acciones asíncronas pendientes por sus ID y comienza a registrar el historial cuando ve una acción con el
status: ''request''
; - cuando recibe una acción con
status: ''done''
, reinicia el historial; - cuando recibe una acción con
status: ''fail''
, ajusta el historial para no incluir la acción inicial constatus: ''request''
y vuelve a ejecutar el reductor para volver a calcular el estado actual como si la solicitud nunca hubiera ocurrido.
Por supuesto, no he proporcionado la implementación, pero esto debería darle una idea de cómo implementar actualizaciones optimistas de una manera Redux.
Actualización: según el comentario del OP, redux-optimist parece hacer exactamente eso.
He estado trabajando con actualizaciones optimistas en una aplicación React + Flux y vi dos cosas:
- ¿Qué sucede si un usuario intenta cerrar la ventana cuando existen algunas acciones incompletas? Por ejemplo, en Facebook, aparece un mensaje en el muro incluso si no se persistió realmente (esto es lo que hacen las actualizaciones optimistas, una aplicación más receptiva para el usuario). Pero, si un usuario publica en el muro e inmediatamente cierra la aplicación (al cerrar sesión o cerrar la ventana), la publicación podría fallar y no recibiría ninguna alerta.
- No me gusta la idea de que las tiendas gestionen sus propias entidades (por ejemplo, mensajes) y la situación de la acción activada para persiste un mensaje (¿se está cargando, ¿ha fallado?). Mezcla cosas.
Así que trabajo en esto y creo un ActionStore para administrar el estado de las acciones activadas por los componentes. Aquí está el código fuente y aquí hay una demostración en vivo.
Funciona más o menos así:
- La raíz de la jerarquía de componentes (contenedor en redux) busca el nextId de una nueva acción y se la pasa a sus hijos como accesorios (esto es feo).
- Un componente secundario activa una acción: mantiene el identificador de acción para pedirlo a la tienda después y llamar al creador de la acción.
- El creador de la acción crea una nueva acción y devuelve una función al middleware.
- La función devuelta de la Acción crea una nueva Promesa con la llamada a la API y envía una acción de tipo XX_START.
- El ActionStore escucha la acción XX_START y la guarda.
- El componente hijo recibe el nuevo estado y encuentra la acción con el ID guardado y le pregunta la situación actual: carga, éxito o falla.
He hecho esto principalmente para separar el estado de las "entidades" del estado de las acciones, pero también permite acciones de reactivación con la misma carga útil (esto podría ser útil cuando recibimos 500 estados de respuesta si el servidor está temporalmente apagado o si la señal suelta del usuario).
Además, tener un almacén de acciones permite preguntar fácilmente si están pendientes de acciones antes de que el usuario cierre la sesión o cierre la ventana.
Nota: estoy trabajando con una aplicación web de una sola página de aplicación contra una API Rest, no creo que use esto en la representación del lado del servidor
¿Es una opción viable crear un ActionStore o estoy rompiendo algunos fundamentos de Redux / Flux? Esto podría acabar con la posibilidad de usar React Hot Reloading and Time traveling?
Debes responder sin piedad, probablemente he hecho un montón de cosas feas pero estoy aprendiendo React / Redux.