【问题标题】:Reroute on specific state of Redux store根据 Redux 存储的特定状态重新路由
【发布时间】:2016-05-07 17:11:30
【问题描述】:

我将 React.js 与 Redux、React-Router 和 React-Router-Redux 一起使用。

我想在商店达到特定状态时手动重新路由(或调用操作)。如果商店有特定的状态,我该如何收听?我在哪里重新路由或调用操作?

【问题讨论】:

  • 您能详细说明您要达到的目标吗?我感觉到这里存在XY 问题,您可能会在更多上下文中得到更好的答案。一般来说,您不需要根据状态更改状态。
  • 考虑以下场景。部分状态是从一些数据库(多个)异步加载的。当数据库事务完成后,我想调用一个动作并在该动作中更改路由。数据库事务的每一端都记录在存储状态中。
  • 那么本质上,一旦一系列异步请求完成,你怎么能改变路由呢?不是当商店中有属性等于某些特定的已知值时?
  • 是的,但是由于我有多个数据库,因此我必须将已初始化的数据库存储在某个地方(并且只有在所有数据库都准备好后才重新路由)。我在哪里存储...在 Redux 商店:-)
  • 但是我越想你和 Henrik 是对的。也许那些初始化的东西不适合商店。我会在其他地方处理它。

标签: reactjs react-router redux


【解决方案1】:

如果这些调用是异步的,那么使用异步操作创建器,promise 会很好地处理这个问题。

// Action creator
function doTheStuff(someData, router) {
    return dispatch => {
        dispatch(somePendingAction());
        return myRequestLib.post('/the-endpoint/', someData)
            .then((response) => {
                if (response.isTransactionDone) {
                    dispatch(transactionDoneAction(response));
                    router.transitionTo('/theUrl');
                }
            });
    }
}

我不会把它放到商店里,因为我相信商店唯一的工作就是包含/处理数据。

【讨论】:

    【解决方案2】:

    要在一系列其他操作完成并保存到商店时启动页面更改,请发送以下redux-thunk。这里的关键是你有一个返回承诺的 thunk 链,然后一旦它们都完成,你可以用另一个动作更新路由器。

    在组件中:

    import React from 'react';
    import { push } from 'react-router-redux';
    import { connect } from 'react-redux';
    import { doStuff, doMoreStuff } from './actions';
    
    class SomeComponent extends React.Component {
      ...
      onClick = e => {
        const { doStuff, doMoreStuff, push } = this.props; // these are already wrapped by dispatch because we use connect
        ...
        doStuff()
          .then(r => doMoreStuff())
          .then(r => push('/newPath')) // if actions succeeded, change route
          .catch(e => console.warn('doStuff() or doMoreStuff failed'));
        ...
      }
      ...
    }
    
    export default connect(null, { doStuff, doMoreStuff, push })(SomeComponent);
    

    ./actions.js中的一些操作:

    export function doStuff() {
      return (dispatch, getState) => {
        return API.getSomeInfo()
          .then(info => dispatch({ type: 'GET_SOME_INFO', payload: info }))
      }
    }
    
    export function doMoreStuff() {
      return (dispatch, getState) => {
        return API.getSomeMoreInfo()
          .then(info => dispatch({ type: 'GET_SOME_MORE_INFO', payload: info }));
      }
    }
    

    或者,您可以做出如下所示的单个承诺,重定向发生的地方:

    export function doAllStuff() {
      return dispatch => {
        return Promise.all(doStuff(), doAllStuff())
          .then(results => dispatch(push('/newPath')))
          .catch(e => console.warn('Not all actions were successful'))
      }
    }
    

    启动它的组件代码就是

    onClick = e => {
      ...
      doAllStuff(); // Since we caught the promise in the thunk, this will always resolve
      ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-19
      • 2020-01-12
      • 2016-03-06
      • 2016-10-21
      • 2020-09-05
      • 2021-07-22
      • 2015-06-23
      相关资源
      最近更新 更多