【问题标题】:Add Loading Indicator for React-Redux app with Promise Middleware使用 Promise 中间件为 React-Redux 应用程序添加加载指示器
【发布时间】:2017-09-25 11:20:00
【问题描述】:

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

但是,在我的应用程序中,我正在调度一个返回“类型”和“有效负载”的操作,这是一个承诺。中间件 redux-promise 然后“自动”转换该承诺有效负载并将其发送到减速器。 换句话说,中间件在幕后为 Promise 执行 .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);

【问题讨论】:

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


    【解决方案1】:

    当您在使用redux-promise 时以Promise 作为其有效负载分派操作时,redux-promise 中间件将捕获该操作,等到Promise 解析或拒绝,然后重新分派该操作,现在使用Promise 的结果作为其有效负载。这意味着您仍然可以处理您的操作,并且一旦您处理它,您就知道它已经完成了。所以你是对的,reducer 是处理这个问题的正确地方。

    不过,你说得对,reducer 不应该有副作用。他们应该只建立新的状态。因此,答案是通过在 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 存储中。使用该标志,您可以有条件地呈现加载指示器。 :)

    【讨论】:

      【解决方案2】:

      我相信 Pedro 的回答应该能让你开始,但我最近在我的应用程序中做了非常准确的 loader/pre-loader

      最简单的方法是。

      1. 在您的一个 reducer 中的 state 对象中创建一个新键,并将其命名为 showLoader: false
      2. 在与之前相同的容器中(带有按钮的容器),创建一个mapStateToProps 并获取该状态属性showLoader
      3. 在包含您尝试触发loader 的按钮的container 内,添加一个调用actiononClick 事件,例如displayLoader。在同一函数中还将this.props.showLoader 设置为true
      4. 创建一个displayLoader 操作,编写如下内容:

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

      希望对你有帮助!

      【讨论】:

        猜你喜欢
        • 2018-05-16
        • 2021-03-19
        • 2020-02-19
        • 2020-11-05
        • 2016-05-29
        • 2018-07-21
        • 1970-01-01
        • 2020-05-10
        • 2017-10-11
        相关资源
        最近更新 更多