Подтвердить что ты не робот

Асинхронные действия в Redux

У меня есть приложение React, мне нужно сделать ajax-вызов (чтобы узнать) в онлайн-службу (async) с помощью Redux.

Это мой магазин:

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

Я не понимаю, что я делаю неправильно. Действие отлично называется компонентом. Но затем я получаю эту ошибку:

Ошибка: действия должны быть обычными объектами. Используйте специализированное промежуточное программное обеспечение для асинхронных действий.

Думаю, я использую неправильное промежуточное ПО. Что я делаю неправильно?

ИЗМЕНИТЬ

Теперь действие вызывает редуктор, но редуктор после изменения состояния не повторяет метод рендеринга

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

        return state.dueDates = action.dueDates;
4b9b3361

Ответ 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, это была одна из проблем. Другая часть заключалась в том, что утилизатор не применялся должным образом. Я уверен, что compose должна решить проблему.

Ответ 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. На основе документации из репозитория GitHub для redux-thunk

Решение работает для 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)
  );
}