首页 文章

使用Promise Middleware为React-Redux应用添加加载指示器

提问于
浏览
3

我是新来的反应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);

3 回答

  • 1

    我认为我们可以提供机制来处理从承诺开始到承诺结束的中间情况 . 我认为我们必须放弃使用redux-promise处理智能显示/隐藏加载UI . 我们可能需要使用redux-loading-promise-middleware等中间件 .

  • -1

    当您使用 redux-promise 分配一个 Promise 作为其有效负载的操作时, redux-promise 中间件将捕获该操作,等待 Promise 解析或拒绝,然后重新发送操作,现在将 Promise 的结果作为其有效负载 . 这意味着您仍然可以处理您的操作,并且一旦您处理它,您就会知道它正确,因为reducer是处理此问题的正确位置 .

    但是,你也是对的,减压剂不应该有副作用 . 他们应该只 Build 新的国家 . 答案是,通过在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商店中加载数据 . 使用该标志,您可以有条件地渲染加载指示器 . :)

  • 0

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

    最简单的方法是 .

    • 在其中一个reducers中的 state 对象中创建一个新键,并将其命名为 showLoader: false .

    • 在与之前相同的容器(带按钮的容器)中,创建 mapStateToProps 并获取该状态属性 showLoader .

    • container 内部,你持有试图触发 loader 的按钮,添加 onClick 事件,调用 action ,比如 displayLoader . 在同一个函数中也将 this.props.showLoader 设置为 true

    • 创建 displayLoader 动作写如下:

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

    希望能帮助到你!

相关问题