在redux中修改响应数据的合理位置在哪里?

Chr*_*ris 9 reactjs redux redux-thunk react-redux

使用React,Redux和Thunk的组合,我有以下内容:

actions.js

import $ from 'jquery';
import * as types from '../constants/ActionTypes';
import { API_PATH } from '../constants/Config';

export function coursesLoaded(courses) {
    return { type: types.COURSES_LOADED, courses };
}

export function fetchData() {
    return (dispatch) => {
        return $.getJSON(API_PATH).then((response) => {
            dispatch(coursesLoaded(response.result));
        });
    };
}
Run Code Online (Sandbox Code Playgroud)

reducer.js

import { routerReducer as routing } from 'react-router-redux';
import { combineReducers } from 'redux';
import * as types from '../constants/ActionTypes';

const initialState = {
    courses: [],
};

function main(state = initialState, action) {
    switch(action.type) {
        case types.COURSES_LOADED:
            return {
                ...state,
                courses: action.courses,
            };
        default:
            return state;
    }
}

const rootReducer = combineReducers({ main, routing });

export default rootReducer;
Run Code Online (Sandbox Code Playgroud)

上面的两个片段坐得很好,我觉得它们符合Redux的意图.我现在想要在响应容器之前对响应中返回的字段进行一些修改.

例如,响应可能是:

[
    { code: "R101", name: "Intro to Redux", author: "Dan" },
    { code: "R102", name: "Middleware", author: "Dan" },
]
Run Code Online (Sandbox Code Playgroud)

我想将其更改为(简单的简单示例):

[
    { code: "R101", name: "Intro to Redux", author: "Dan", additionalProperty: "r101_intro_to_redux" },
    { code: "R102", name: "Middleware", author: "Dan", additionalProperty: "r102_middleware" },
]
Run Code Online (Sandbox Code Playgroud)

迄今为止的研究

选项一 看看Redux上的异步示例,我可以看到这里有一个轻松的响应:https: //github.com/reactjs/redux/blob/master/examples/async/actions/index.js#L33

选项二 看看其他Stackoverflow问题,它让我相信保持它的行为更有意义,因为reducers应该是什么修改状态(但也许这并不算作状态?): Redux - 在哪里准备数据

选项三 我倾向于认为这是中间件的工作 - 这就是normalizr处理它的方式,但我找不到任何非被动中间件示例.如果中间件是这里,中间件应该调度某种SET_STATE动作,还是可以在中间件中自由更新状态?

编辑

使用一些中间件进行实验,例如:

import { lowerCase, snakeCase } from 'lodash';
import * as types from '../constants/ActionTypes';

    export default store => next => action => {
        if(action.type == types.COURSES_LOADED) {
            action.courses = action.courses.map((course) => {
                course.additionalProperty = snakeCase(lowerCase(`${course.code} ${course.name}`));
                return course;
            });
        }
        return next(action);
    }
Run Code Online (Sandbox Code Playgroud)

它似乎工作正常 - 这确实是中间件的意图吗?原始问题成立 - 它在哪里理想?

Mij*_*amo 13

至于我,我做这样的动作事物(无论是coursesLoadedfetchData).

以下是原因:

  • 这不是商店材料,这只是外部数据管理,所以与应该改变商店STATE的Reducer无关
  • 不同的减速器实际上可能需要相同的校正数据,additionalProperty例如,您可以使用另一个减速器来收集所有用于实现目的的减速器,因此在动作中执行此操作可确保将正确的数据发送到所有减速器.
  • 这不是中间件的典型工作,这仅适用于一个操作,而中间件如果通过一堆操作以相同的方式使用则会很有用.此外,使用中间件更加模糊,并将其与读者分开.动作 - >减速器更简单,没有任何主要缺点.