使用Promise Middleware

时间:2017-04-27 15:08:11

标签: reactjs redux react-redux redux-promise redux-promise-middleware

我是新来的反应redux。我想在用户按下搜索按钮时添加加载文本,并在数据返回或操作完成时关闭文本。 在普通的异步函数中,我可以在回调之前和之后切换isLoading标志。

但是,在我的应用程序中,我正在调度一个返回“类型”和“有效负载”的操作,这是一个承诺。然后,中间件redux-promise会“自动”转换该promise负载并将其发送到reducer。 换句话说,中间件对场景后面的承诺执行.then操作,并为我的reducer提供正确的数据。

在这种情况下,我不确定如何在视图中添加加载文本,因为只要我调用this.props.getIdByName(this.state.value),我就不知道数据什么时候回来了。 对我来说,合乎逻辑的地方就是在reducer中,因为那时数据会回来。但是,我相信这会是一种糟糕的方式,因为减速器不应该执行这样的任务?

在我的组件中,我的提交有以下功能

  handleSubmit(e) {
    e.preventDefault();
    this.props.getIdByName(this.state.value);
  }

在我的actions / index.js文件中,我有以下动作生成器

export function getIdByName(name) {
    const FIELD = '/characters'
    let encodedName = encodeURIComponent(name.trim());
    let searchUrl = ROOT_URL + FIELD + '?ts=' + TS + '&apikey=' + PUBLIC_KEY + '&hash=' + HASH + '&name=' + encodedName;
    const request = axios.get(searchUrl)

    return {
        type: GET_ID_BY_NAME,
        payload: request
    }
}

在我的reducers / reducers.jsx里面

export default function (state = INITIAL_STATE, action) {
    switch (action.type) {
        case GET_ID_BY_NAME: 
            console.log(action.payload.data.data.results[0].id); <-- here the data comes back correctly because reduer called the promise and gave back the data for me
            return {...state, id: action.payload.data.data.results[0].id};
        default:
            return state;
    }
}

在我的主index.js文件中,我使用以下中间件创建了商店

const createStoreWithMiddleware = applyMiddleware(
    promise,
    thunk
)(createStore);

2 个答案:

答案 0 :(得分:1)

当您使用Promise分派使用redux-promise作为其有效负载的操作时,redux-promise中间件将捕获该操作,等到Promise结算或拒绝,然后重新调度该操作,现在将Promise的结果作为其有效负载。这意味着您仍然可以处理您的操作,并且只要您处理它就知道它已经完成了。因此,你是正确的,减速器是处理这个问题的最佳选择。

然而,你也是对的,减压剂不应该有副作用。他们应该只建立新的国家。答案是,通过在Redux中更改应用程序的状态,可以显示和隐藏加载指示符:)

我们可以在Redux商店中添加一个名为isLoading的标志:

const reducers = {
    isLoading(state = false, action) {
        switch (action.type) {
          case 'START_LOADING':
            return true;
          case 'GET_ID_BY_NAME':
            return false;
          default:
            return state;
        }
    },
    // ... add the reducers for the rest of your state here
}

export default combineReducers(reducers);

每当您打算致电getIdByName时,请在调用之前调度类型为'START_LOADING'的操作。当getIdByNameredux-promise重新分配时,您将知道加载已完成,isLoading标记将被设置为false。

现在我们有一个标志,指示我们是否在Redux商店中加载数据。使用该标志,您可以有条件地渲染加载指示器。 :)

答案 1 :(得分:0)

我确信佩德罗的答案应该让你开始,但我最近在我的应用中做了非常精确的loader/pre-loader

最简单的方法是。

  1. 在其中一个Reducer中的state对象中创建一个新密钥,并将其命名为showLoader: false
  2. 在与之前相同的容器(带按钮的容器)中,创建一个mapStateToProps并获取该状态属性showLoader
  3. 在包含您尝试触发container的按钮的loader内,添加一个onClick事件,调用action,说displayLoader 。在同一功能中,还将this.props.showLoader设置为true
  4. 创建一个displayLoader动作,写成如下:

    function displayLoader() {
        return {
            type: DISPLAY_LOADER,
            payload: {}
        }
    }
    
  5. 在缩减器中,请抓住此操作,并在收到所需的showLoader时将false设置回payload

  6. 希望它有所帮助!