在成功的异步 redux 操作上转换到另一条路线
Posted
技术标签:
【中文标题】在成功的异步 redux 操作上转换到另一条路线【英文标题】:Transition to another route on successful async redux action 【发布时间】:2015-12-13 06:22:20 【问题描述】:我有一组非常简单的 react 组件:
container
挂钩到 redux 并处理操作、商店订阅等
list
显示我的项目列表
new
是一种向列表中添加新项目的表单
我有一些react-router 路由如下:
<Route name='products' path='products' handler=ProductsContainer>
<Route name='productNew' path='new' handler=ProductNew />
<DefaultRoute handler=ProductsList />
</Route>
这样list
或form
会显示,但不会同时显示。
我想做的是在成功添加新项目后让应用程序重新路由回列表。
到目前为止,我的解决方案是在异步 dispatch
之后添加一个 .then()
:
dispatch(actions.addProduct(product)
.then(this.transitionTo('products'))
)
这是执行此操作的正确方法还是我应该以某种方式触发另一个操作来触发路由更改?
【问题讨论】:
你看过github.com/acdlite/redux-react-router 吗?它将路由存储存储在 redux 中,因此您可以触发路由更改作为 redux 操作。 我已经查看了redux-react-router
,这需要大量重构,因此可能需要等待。如果我同时提出解决方案,我会发布答案
@Dmitry 那么问题是一旦更新了道具(例如 isAuthenticated 标志),您从哪里触发。 componentWillReceiveProps?
【参考方案1】:
如果您不想使用像Redux Router 这样更完整的解决方案,您可以使用Redux History Transitions,它可以让您编写如下代码:
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'
)
;
这类似于what you suggested,但更复杂一点。它仍然使用相同的 history 库,因此它与 React Router 兼容。
【讨论】:
payload: userId: 123
后面需要一个逗号【参考方案2】:
我最终创建了一个超级简单的中间件,大致如下:
import history from "../routes/history";
export default store => next => action =>
if ( ! action.redirect ) return next(action);
history.replaceState(null, action.redirect);
因此,您只需确保您的 successful
操作具有 redirect
属性。另请注意,此中间件不会触发next()
。这是故意的,因为路由转换应该是动作链的末端。
【讨论】:
不适用于 thunk 中间件?如果你从 'LOGIN_STARTED' 移动到 'LOGIN_SUCCESSFUL' 并且不调用 next 什么都不会发生。 这是最小的工作解决方案。感谢分享。 这里的../routes/history
是什么?
这里的../router/history 是什么?这仍然有效吗?【参考方案3】:
对于那些使用中间件 API 层来抽象他们对 isomorphic-fetch 之类的使用的人,并且恰好也在使用 redux-thunk,您可以简单地将您的 dispatch
Promise 链接到您的操作中,就像这样:
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));
);
;
这减少了按照 here 的建议将库添加到您的代码中的需要,并且还可以很好地将您的操作与它们的重定向放在一起,就像在 redux-history-transitions 中所做的那样。
这是我的商店的样子:
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;
【讨论】:
真的有用吗...因为它不适合我 无法正常工作,因为 url 被重定向但我在页面中的内容没有改变。即使 url 改变了它也会显示相同的页面.. 您在使用路由器吗?哪个路由器和什么附加组件?这段代码是用 React-Router 和 React-Router-Redux 编写的 这对我有用,但您的商店中必须包含routerMiddleware
github.com/reactjs/…
对于像我这样想知道函数 push
来自哪里的人:import push from 'react-router-redux'
【参考方案4】:
我知道我迟到了,因为 react-navigation 已经包含在 react-native 文档中,但对于在他们的应用程序中使用/使用 Navigator api 的用户来说,它仍然很有用。 我尝试过的有点骇人听闻,一旦 renderScene 发生,我就会将导航器实例保存在对象中-
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/>
我的 api 文件是这样的
'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;
现在在你的行动中你可以简单地调用
api.navigator.push(Name:'routeName', 数据:WHATEVER_YOU_WANTED_TO_PASS)
您只需要从模块中导入您的 api。
【讨论】:
【参考方案5】:如果您使用react-redux 和react-router,那么我认为this link 提供了一个很好的解决方案。
这是我使用的步骤:
通过在 react-router<Route/>
组件中渲染组件或使用 withRouter
创建高阶组件,将 react-router history
属性传递给您的组件。
接下来,创建您要重定向到的路线(我叫我的to
)。
第三,使用history
和to
调用您的redux 操作。
最后,当您想要重定向时(例如,当您的 redux 操作解析时),请致电 history.push(to)
。
【讨论】:
以上是关于在成功的异步 redux 操作上转换到另一条路线的主要内容,如果未能解决你的问题,请参考以下文章
将信息从一条路线传递到另一条路线:Flask ignoring redirect requests