react-router - react - redux router dom
Cómo sincronizar el estado de Redux y los parámetros de consulta de URL (5)
Tengo una página web con un panel de búsqueda. El panel de búsqueda tiene varios campos de entrada: id, tamaño, ...
Lo que quiero es cuando el usuario establece valores de búsqueda (por ejemplo: id = 123 y size = 45) y presiona un botón de búsqueda:
- searchState en Redux reductor debe actualizarse con nuevos valores de búsqueda (id = 123 y size = 45)
- La URL debe cambiarse a " http://mydomain/home?id=123&size=45 "
Y, por otro lado, si el usuario cambia la URL a http://mydomain/home?id=111&size=22 entonces:
- searchState en reductor debe cambiarse con nuevos valores de búsqueda (id = 111 y size = 22)
- Las entradas del panel de búsqueda de IU deben actualizarse con nuevos valores (id = 111 y size = 22)
¿Cómo llegar con gol? ¿Qué enrutador debo usar (react-router, redux-router, react-router-redux ot other)?
Así es como he estado manejando el primer escenario:
-
Cuando el valor de entrada cambia, su componente desencadena una devolución de llamada que se pasó como accesorio desde su contenedor.
-
En la devolución de llamada, el contenedor distribuye la acción responsable de actualizar el estado de Redux cuando se produce el evento.
-
En la línea que sigue inmediatamente a la llamada a la acción, uso
this.context.router.push()
y le paso la url con la cadena de consulta correcta.
No estoy seguro de que este sea el enfoque correcto. Me pareció preferible actualizar la URL primero porque, en mi opinión, la cadena de consulta debería ser un reflejo del estado en lugar del maestro de la misma.
Con respecto al escenario inverso, realmente no estoy seguro. Parece que configurar manualmente la URL desencadenaría una recarga completa, pero podría estar equivocado.
En cuanto a qué enrutador usar, estoy usando React Router por sí mismo. Realmente no estaba encontrando valor en el uso de los demás y esta discusión fue el factor decisivo para mí.
Recientemente he terminado de trabajar en un problema similar a este. Usé MobX como mi tienda y redux-router como mi enrutador. (Lo hice bien con react-router, pero necesitaba despachar una acción de empuje fuera del componente; redux como tienda global funciona muy bien aquí)
Mi solución ha sido similar a lo que ha descrito cantera: el estado de mi enrutador es simplemente un reflejo del estado del formulario. Esto tiene la ventaja adicional de no tener que abandonar mi estado de formulario y depender completamente del estado del enrutador.
En el primer escenario,
1) Actualizo mi entrada de formulario como de costumbre, lo que desencadena una nueva representación en el componente de resultados.
2) En
componentDidUpdate()
del componente de resultados, utilizo los accesorios de formulario para construir la cadena de consulta actualizada.
3) Empujo la cadena de consulta actualizada al estado del enrutador. Esto es solo por el efecto de actualizar la URL.
Para el segundo escenario
1) En el
onEnter
en el componente de
Route
raíz, obtengo la cadena de consulta disponible y la analizo en los valores de formulario iniciales.
2) Actualizo mi tienda con los valores. Esto es solo para la primera carga de la página y la única vez que el estado del enrutador dicta el estado del formulario.
Editar: esta solución no tiene en cuenta el caso cuando vuelve al historial de su navegador, porque la URL no actualizará su estado.
Recomendaría la nueva herramienta react-url-query que hará que la sincronización sea bastante sencilla.
Sugeriría simplemente usar
React Router
directamente y
no
mantener
searchState
en Redux.
React Router inyectará parámetros de URL en sus componentes, y puede usarlos en
mapStateToProps(state, ownProps)
para calcular los accesorios finales.
Si realmente desea ver los cambios de ruta como acciones, puede usar react-router-redux para la sincronización bidireccional, pero no le dará los parámetros en el estado, solo la ubicación actual. El único caso de uso es si desea grabar y reproducir acciones, y hacer que la barra de URL se actualice a medida que las reproduce.
De ninguna manera es necesario; en la mayoría de los casos, solo usar React Router directamente es suficiente.
En resumen : podría usar redux-query-sync para mantener redux-query-sync los parámetros y campos de URL en la tienda. Funciona sin ningún enrutador.
Historia más larga : luchando con la misma pregunta, primero aprecié la answer Dan Abramov, sugiriendo (en mis palabras) considerar la URL como una ''segunda tienda'', una parte del estado de la aplicación fuera de la tienda Redux. Pero luego descubrí que tener dos tipos de ''tiendas'' hace que sea difícil modificar el código, por ejemplo, mover cosas de una a otra, porque cada ''tienda'' tiene una interfaz diferente. Como desarrollador, prefiero seleccionar cualquiera de los campos en mi estado Redux y exponerlos en la URL, como si la ubicación fuera una pequeña ventana a (una parte de) mi estado.
Por lo tanto, acabo de publicar redux-query-sync, para permitirle proporcionar una función de selector para seleccionar un valor del estado, que luego se expone en la ubicación de la ventana en el nombre de parámetro que especifique. Para permitir que se sincronice en la otra dirección, por lo tanto, desde la URL al estado de Redux (p. Ej., Cuando la aplicación se carga inicialmente), puede proporcionar un creador de acciones al que se le pasará el valor del parámetro, para que su reductor pueda actualizar el estado en consecuencia.