Javascript Redux 中的异步操作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35530547/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 17:50:45  来源:igfitidea点击:

Async actions in Redux

javascriptasynchronousreactjsreduxredux-thunk

提问by Pablo

I have a React App, I need to make an ajax call (in order to learn) to a online service (async) with Redux.

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

This is my store:

这是我的店铺:

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


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

This is the actions:

这是动作:

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))
    )
}

And this is the reducer:

这是减速器:

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

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

I dont get what I'm doing wrong. The action is being called perfectly from the component. But then I get this error:

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

Error: Actions must be plain objects. Use custom middleware for async actions.

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

I guess I'm using wrong the react-thunk middleware. What am I doing wrong?

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

EDIT

编辑

Now the action is calling to the reducer, but the reducer, after changing state, is not re-running the render method

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

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

        return state.dueDates = action.dueDates;

采纳答案by rishat

I think you should be using composefunction, so it's like

我认为你应该使用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 allows an action creator to return a function instead of plain-object, so you use it like

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

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

You were returning a Promise object, that was one part of the problem. Another part was that redux-thunk hasn't been properly applied. I bet composeshould get the problem solved.

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

回答by Alexander Mills

The accepted answer is either outdated, wrong or over-convoluted. Here are the docs on the compose subject:

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

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

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

so we can do it like this instead:

所以我们可以这样做:

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))
);

回答by Kevin Farrugia

I believe it is possible to have a working solution without using the composefunction too. Based on the documentation from the GitHub repo for redux-thunk

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

Solution works for redux-thunk: ^2.0.0

解决方案适用于 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)
  );
}