react javascript reactjs react-router redux

javascript - reactjs redux



Transición a otra ruta en una acción asíncrona redux exitosa (5)

Para aquellos que usan una capa de API de middleware para abstraer su uso de algo como isomorphic-fetch , y también están usando redux-thunk , simplemente pueden encadenar su Promesa de dispatch dentro de sus acciones, de esta manera:

import { push } from ''react-router-redux''; const USER_ID = // imported from JWT; function fetchUser(primaryKey, opts) { // this prepares object for the API middleware } // this can be called from your container export function updateUser(payload, redirectUrl) { var opts = { method: ''PUT'', headers: { ''Content-Type'': ''application/json'' }, body: JSON.stringify(payload) }; return (dispatch) => { return dispatch(fetchUser(USER_ID, opts)) .then((action) => { if (action.type === ActionTypes.USER_SUCCESS) { dispatch(push(redirectUrl)); } }); }; }

Esto reduce la necesidad de agregar bibliotecas a su código como se sugiere here , y también co-ubica muy bien sus acciones con sus redireccionamientos como se hace en redux-history-transitions .

Así es como se ve mi tienda:

import { createStore, applyMiddleware } from ''redux''; import rootReducer from ''../reducers''; import thunk from ''redux-thunk''; import api from ''../middleware/api''; import { routerMiddleware } from ''react-router-redux''; export default function configureStore(initialState, browserHistory) { const store = createStore( rootReducer, initialState, applyMiddleware(thunk, api, routerMiddleware(browserHistory)) ); return store; }

Tengo un conjunto bastante simple de componentes de reacción:

  • container que se engancha en redux y maneja las acciones, almacena suscripciones, etc.
  • list que muestra una lista de mis artículos
  • new que es un formulario para agregar un nuevo elemento a la lista

Tengo algunas rutas de react-router siguiente manera:

<Route name=''products'' path=''products'' handler={ProductsContainer}> <Route name=''productNew'' path=''new'' handler={ProductNew} /> <DefaultRoute handler={ProductsList} /> </Route>

para que se muestre la list o el form pero no ambos.

Lo que me gustaría hacer es que la aplicación vuelva a enrutarse a la lista una vez que se haya agregado con éxito un nuevo elemento.

Mi solución hasta ahora es tener un .then() después del dispatch asíncrono:

dispatch(actions.addProduct(product) .then(this.transitionTo(''products'')) )

¿Es esta la forma correcta de hacer esto o debería activar otra acción de alguna manera para activar el cambio de ruta?


Sé que llego un poco tarde en la fiesta, ya que react-navigation ya está incluido en la documentación de react-native, pero aún así puede ser útil para el usuario que ha usado / usando Navigator api en sus aplicaciones. lo que probé es un poco hack, estoy guardando la instancia del navegador en el objeto tan pronto como renderScene sucede

renderScene(route, navigator) { const Component = Routes[route.Name] api.updateNavigator(navigator); //will allow us to access navigator anywhere within the app return <Component route={route} navigator={navigator} data={route.data}/> }

mi archivo api es algo como esto

''use strict''; //this file includes all my global functions import React, {Component} from ''react''; import {Linking, Alert, NetInfo, Platform} from ''react-native''; var api = { navigator, isAndroid(){ return (Platform.OS === ''android''); }, updateNavigator(_navigator){ if(_navigator) this.navigator = _navigator; }, } module.exports = api;

ahora en tus acciones simplemente puedes llamar

api.navigator.push ({Nombre: ''routeName'', datos: WHATEVER_YOU_WANTED_TO_PASS)

solo necesita importar su api desde el módulo.


Si está utilizando react-redux y react-router , creo que este enlace proporciona una excelente solución.

Aquí están los pasos que utilicé:

  • Pase un accesorio de history enrutador de reacción a su componente, ya sea renderizando su componente dentro de un componente <Route/> enrutador de reacción o creando un Componente de orden superior usando withRouter .
  • A continuación, cree la ruta a la que desea redirigir (llamé a la mía).
  • Tercero, llame a su acción redux con history y to .
  • Finalmente, cuando desee redirigir (por ejemplo, cuando se resuelva su acción redux), llame a history.push(to) .

Si no desea usar una solución más completa como github.com/acdlite/redux-react-router , puede usar Redux History Transitions que le permite escribir código como este:

export function login() { return { type: LOGGED_IN, payload: { userId: 123 } meta: { transition: (state, action) => ({ path: `/logged-in/${action.payload.userId}`, query: { some: ''queryParam'' }, state: { some: ''state'' } }) } }; }

Esto es similar a lo que sugirió, pero un poco más sofisticado. Todavía usa la misma biblioteca de history debajo del capó, por lo que es compatible con React Router.


Terminé creando un middleware súper simple que se ve así:

import history from "../routes/history"; export default store => next => action => { if ( ! action.redirect ) return next(action); history.replaceState(null, action.redirect); }

Entonces, a partir de ahí, solo debe asegurarse de que sus acciones successful tengan una propiedad de redirect . También tenga en cuenta que este middleware no se activa next() . Esto es a propósito, ya que una transición de ruta debe ser el final de la cadena de acción.