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 usandowithRouter
. - 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
yto
. -
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.