【问题标题】:Async actions in ReduxRedux 中的异步操作
【发布时间】:2016-06-02 12:23:18
【问题描述】:

我有一个 React 应用程序,我需要使用 Redux 对在线服务(异步)进行 ajax 调用(以便学习)。

这是我的商店:

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import duedates from './reducers/duedates'


export default applyMiddleware(thunk)(createStore)(duedates);

这是动作:

import rest from '../Utils/rest';

export function getDueDatesOptimistic(dueDates){
    console.log("FINISH FETCH");
    console.log(dueDates);
    return {
        type: 'getDueDate',
        dueDates
    }
}

export function waiting() {
    console.log("IN WAIT");
    return {
        type: 'waiting'
    }
}


function fetchDueDates() {
    console.log("IN FETCH");
    return rest({method: 'GET', path: '/api/dueDates'});
}

export function getDueDates(dispatch) {
    console.log("IN ACTION");
    return fetchDueDates().done(
        dueDates => dispatch(getDueDatesOptimistic(dueDates.entity._embedded.dueDates))
    )
}

这是减速器:

export default (state = {}, action) => {
  switch(action.type) {
    case 'getDueDate':
        console.log("IN REDUCER")

        return state.dueDates = action.dueDates;
    default:
        return state
  }
}

我不明白我做错了什么。该操作正在从组件中完美调用。但后来我得到这个错误:

错误:动作必须是普通对象。使用自定义中间件进行异步操作。

我想我使用了错误的 react-thunk 中间件。 我做错了什么?

编辑

现在action正在调用reducer,但是reducer在改变状态后并没有重新运行render方法

    case 'getDueDate':
        console.log("IN REDUCER")

        return state.dueDates = action.dueDates;

【问题讨论】:

    标签: javascript asynchronous reactjs redux redux-thunk


    【解决方案1】:

    我认为你应该使用compose 函数,所以它就像

    import {
      createStore,
      applyMiddleware,
      compose
    } from 'redux';
    import thunk from 'redux-thunk';
    import duedates from './reducers/duedates'
    
    export default compose(applyMiddleware(thunk))(createStore)(duedates);
    

    Thunk 允许动作创建者返回一个函数而不是普通对象,所以你可以像使用它一样

    export function getDueDates() {
      return dispatch => {
        console.log("IN ACTION");
        fetchDueDates().done(
          dueDates => dispatch(getDueDatesOptimistic(dueDates.entity._embedded.dueDates))
        )
      };
    }
    

    你返回了一个 Promise 对象,这是问题的一部分。另一部分是 redux-thunk 没有被正确应用。我打赌compose 应该可以解决问题。

    【讨论】:

    • 太好了,现在似乎可以工作了。但是在reducer中,当我return状态return state.dueDates = action.dueDates;时,它不会再次调用render..我应该添加其他东西吗?
    • 现在,在您的代码示例中,这两个操作都不会改变状态。您返回状态本身。您能否更新您的问题,以便我(或其他任何人)了解当前情况?
    • 更新了,现在我return state.dueDates = action.dueDates;
    • 你不应该那样做。此表达式返回正确部分的值,这不是您想要减少状态的方式。相反,请尝试使用对象传播:return {...state, dueDates: action.dueDates}.
    • ugghh,抱歉 Redux,但这一点漂亮....真的“导出默认 compose(applyMiddleware(thunk))(createStore)(duedates);” ?
    【解决方案2】:

    接受的答案要么是过时的,要么是错误的,要么是过于复杂的。以下是撰写主题的文档:

    http://redux.js.org/docs/api/compose.html

    所以我们可以这样做:

    import {createStore, combineReducers, compose, applyMiddleware} from 'redux';
    import thunk from 'redux-thunk';
    
    const reducer = combineReducers({
        user: userReducer,
        items: itemsReducer
    });
    
    
    // here is our redux-store
    const store = createStore(reducer,
        compose(applyMiddleware(thunk))
    );
    

    【讨论】:

      【解决方案3】:

      我相信在不使用compose 函数的情况下也可以有一个可行的解决方案。基于redux-thunk 的 GitHub 存储库中的文档

      解决方案适用于redux-thunk: ^2.0.0

      import { createStore, applyMiddleware } from 'redux';
      import thunk from 'redux-thunk';
      import duedates from './reducers/duedates'
      
      export function configureStore(initialState = {}) {
        return createStore(
          duedates,
          initialState,
          applyMiddleware(thunk)
        );
      }
      

      【讨论】:

      • 嗨,Kevin,createReducer 来自哪里?
      • 嗨@RishatMuhametshin,我已经更正了上面的例子。 createReducer 是一个避免样板代码的函数,取自 react-boilerplate
      • 这对我有用。正如 Kevin 所说,compose 不是必需的。
      • 哇!!!! [抓头] 碰到这个问题是因为import thunkMiddleware from 'redux-thunk'.的导入漏掉了分号
      猜你喜欢
      • 2020-04-23
      • 1970-01-01
      • 2017-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-23
      相关资源
      最近更新 更多