Soy nuevo en React / Redux. Utilizo un middleware fetch api en la aplicación Redux para procesar las API. Es ( redux-api-middleware ). Creo que es la mejor forma de procesar acciones de API asíncronas. Pero encuentro algunos casos que no puedo resolver por mí mismo.
Como dice la página de inicio ( ciclo de vida ), un ciclo de vida de la API de recuperación comienza con el envío de una acción CALL_API y termina con el envío de una acción FSA.
Entonces, mi primer caso es mostrar / ocultar un precargador al buscar API. El middleware enviará una acción FSA al principio y enviará una acción FSA al final. Ambas acciones son recibidas por reductores que solo deberían realizar un procesamiento normal de datos. Sin operaciones de IU, no más operaciones. Tal vez debería guardar el estado de procesamiento en el estado y luego representarlos cuando se actualice la tienda.
pero como hacer esto? ¿Un componente de reacción fluye por toda la página? ¿Qué sucede con la actualización de la tienda a partir de otras acciones? ¡Quiero decir que son más eventos que estados!
Incluso en el peor de los casos, ¿qué debo hacer cuando tengo que usar el diálogo de confirmación nativo o el diálogo de alerta en las aplicaciones redux / react? ¿Dónde deben colocarse, acciones o reductores?
¡Los mejores deseos! Deseo de responder.
fuente
Respuestas:
Yo no lo diría. Creo que los indicadores de carga son un gran caso de IU que se describe fácilmente como una función de estado: en este caso, de una variable booleana. Si bien esta respuesta es correcta, me gustaría proporcionar un código que la acompañe.
En el
async
ejemplo en el repositorio de Redux , reducer actualiza un campo llamadoisFetching
:El componente usa
connect()
React Redux para suscribirse al estado de la tienda y regresaisFetching
como parte delmapStateToProps()
valor de retorno para que esté disponible en los accesorios del componente conectado:Finalmente, el componente usa
isFetching
prop en larender()
función para representar una etiqueta "Cargando ..." (que posiblemente podría ser una ruleta):Cualquier efecto secundario (y mostrar un diálogo es ciertamente un efecto secundario) no pertenece a los reductores. Piense en los reductores como "constructores de estado" pasivos. Realmente no "hacen" cosas.
Si desea mostrar una alerta, hágalo desde un componente antes de enviar una acción o desde un creador de acciones. Cuando se envía una acción, es demasiado tarde para realizar efectos secundarios en respuesta a ella.
Para cada regla, hay una excepción. A veces, la lógica de los efectos secundarios es tan complicada que en realidad desea combinarlos con tipos de acción específicos o con reductores específicos. En este caso, consulte proyectos avanzados como Redux Saga y Redux Loop . Solo haga esto cuando se sienta cómodo con Vanilla Redux y tenga un problema real de efectos secundarios dispersos que le gustaría hacer más manejable.
fuente
Promise.all
en una única promesa y luego enviar una única acción para todas las recuperaciones. O tienes que mantener múltiplesisFetching
variables en tu estado.isFetching
bandera. Se establece para cada conjunto de objetos que se busca. Puede usar la composición reductora para implementar eso.RECEIVE_POSTS
nunca se activa, la señal de carga permanecerá en su lugar a menos que haya creado algún tipo de tiempo de espera para mostrar unerror loading
mensaje.¡Gran respuesta, Dan Abramov! Solo quiero agregar que estaba haciendo más o menos exactamente eso en una de mis aplicaciones (manteniendo isFetching como booleano) y terminé teniendo que convertirlo en un número entero (que termina leyendo como el número de solicitudes pendientes) para admitir múltiples solicitudes simultáneas peticiones.
con booleano:
solicitud 1 comienza -> ruleta encendida -> solicitud 2 comienza -> solicitud 1 termina -> ruleta apagada -> solicitud 2 termina
con entero:
solicitud 1 comienza -> ruleta activada -> solicitud 2 comienza -> solicitud 1 termina -> solicitud 2 termina -> ruleta desactivada
fuente
isFetching
bandera. Si observa de cerca el ejemplo al que vinculé, verá que no hay un objeto conisFetched
sino muchos: uno por subreddit (que es lo que se está recuperando en ese ejemplo).fetchCounter
barra de progreso global para algunos en la parte superior de la pantalla como variosisFetching
indicadores específicos para listas y páginas.Me gustaría agregar algo. El ejemplo del mundo real utiliza un campo
isFetching
en la tienda para representar cuándo se está recuperando una colección de artículos. Cualquier colección se generaliza a unpagination
reductor que se puede conectar a sus componentes para rastrear el estado y mostrar si se está cargando una colección.Me sucedió que quería obtener detalles para una entidad específica que no encaja en el patrón de paginación. Quería tener un estado que representara si los detalles se están obteniendo del servidor, pero tampoco quería tener un reductor solo para eso.
Para solucionar esto agregué otro reductor genérico llamado
fetching
. Funciona de manera similar al reductor de paginación y su responsabilidad es simplemente observar un conjunto de acciones y generar un nuevo estado con pares[entity, isFetching]
. Eso permite alconnect
reductor a cualquier componente y saber si la aplicación está obteniendo datos no solo para una colección sino para una entidad específica.fuente
No me encontré con esta pregunta hasta ahora, pero como no se acepta ninguna respuesta, arrojaré mi sombrero. Escribí una herramienta para este mismo trabajo: react-loader-factory . Tiene un poco más de funcionamiento que la solución de Abramov, pero es más modular y conveniente, ya que no quería tener que pensar después de escribirlo.
Hay cuatro piezas grandes:
const loaderWrapper = loaderFactory(actionsList, monitoredStates);
connect()
devuelve Redux), por lo que puede atornillarlo a sus cosas existentes.const LoadingChild = loaderWrapper(ChildComponent);
ACTION_SUCCESS
yACTION_REQUEST
, por ejemplo). (Por supuesto, podría enviar acciones a otro lugar y simplemente monitorear desde el contenedor si lo desea).El módulo en sí es independiente de redux-api-middleware, pero para eso lo uso, así que aquí hay un código de muestra del README:
Un componente con un cargador envolviéndolo:
Un reductor para que lo monitoree el cargador (aunque puede cablearlo de manera diferente si lo desea):
Espero que en un futuro cercano agregue cosas como tiempo de espera y error al módulo, pero el patrón no será muy diferente.
La respuesta corta a su pregunta es:
fuente
¿Soy el único que piensa que los indicadores de carga no pertenecen a una tienda Redux? Quiero decir, no creo que sea parte del estado de una aplicación per se ...
Ahora, trabajo con Angular2, y lo que hago es que tengo un servicio de "Cargando" que expone diferentes indicadores de carga a través de RxJS BehaviourSubjects .. Supongo que el mecanismo es el mismo, simplemente no almaceno la información en Redux.
Los usuarios de LoadingService simplemente se suscriben a los eventos que desean escuchar.
Mis creadores de acciones de Redux llaman a LoadingService cuando las cosas necesitan cambiar. Los componentes de UX se suscriben a los observables expuestos ...
fuente
Puede agregar oyentes de cambios a sus tiendas, usando
connect()
React Redux o elstore.subscribe()
método de bajo nivel . Debe tener el indicador de carga en su tienda, que el administrador de cambios de tienda puede luego verificar y actualizar el estado del componente. El componente luego procesa el precargador si es necesario, según el estado.alert
yconfirm
no debería ser un problema. Están bloqueando y la alerta ni siquiera toma ninguna entrada del usuario. Conconfirm
, puede establecer el estado en función de lo que el usuario haya hecho clic si la elección del usuario debe afectar la representación del componente. De lo contrario, puede almacenar la elección como variable miembro de componente para su uso posterior.fuente
addNofication(message)
. Otro caso son los precargadores que también son proporcionados por la aplicación nativa del host y activados por su API de JavaScript. Agrego un contenedor para esas API, encomponentDidUpdate
un componente React. ¿Cómo diseño los accesorios o el estado de este componente?Tenemos tres tipos de notificaciones en nuestra aplicación, todas ellas diseñadas como aspectos:
Los tres están en el nivel superior de nuestra aplicación (principal) y están conectados a través de Redux como se muestra en el siguiente fragmento de código. Estos accesorios controlan la visualización de sus aspectos correspondientes.
Diseñé un proxy que maneja todas nuestras llamadas API, por lo tanto, todos los errores de isFetching y (api) están mediados por actionCreators que importo en el proxy. (Aparte, también uso webpack para inyectar una simulación del servicio de respaldo para el desarrollador para que podamos trabajar sin dependencias del servidor).
Cualquier otro lugar de la aplicación que necesite proporcionar algún tipo de notificación simplemente importa la acción correspondiente. Snackbar & Error tienen parámetros para que se muestren los mensajes.
) exportar clase predeterminada Main extiende React.Component {
fuente
Estoy guardando las URL como:
Y luego tengo un selector memorizado (a través de reselección).
Para que la URL sea única en caso de POST, paso alguna variable como consulta.
Y donde quiero mostrar un indicador, simplemente uso la variable getFetchCount
fuente
Object.keys(items).filter(item => items[item] === true).length > 0 ? true : false
porObject.keys(items).every(item => items[item])
cierto.some
lugar deevery
, pero sí, demasiadas comparaciones no necesarias en la primera solución propuesta.Object.entries(items).some(([url, fetching]) => fetching);