10

React、Redux、Thunk を組み合わせて使用​​すると、次のようになります。

アクション.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));
        });
    };
}

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;

上記の 2 つのスニペットはうまく収まり、Redux の意図に沿っているように感じます。コンテナーにヒットする前に、応答で返されるフィールドにいくつかの変更を加えたいと思います。

たとえば、応答は次のようになります。

[
    { code: "R101", name: "Intro to Redux", author: "Dan" },
    { code: "R102", name: "Middleware", author: "Dan" },
]

そして、私はそれを次のように変更したいと思います(簡単にするための簡単な例):

[
    { code: "R101", name: "Intro to Redux", author: "Dan", additionalProperty: "r101_intro_to_redux" },
    { code: "R102", name: "Middleware", author: "Dan", additionalProperty: "r102_middleware" },
]

これまでの研究

オプション 1 Redux の非同期の例を見ると、ここで応答に軽いタッチがあることがわかります: https://github.com/reactjs/redux/blob/master/examples/async/actions/index.js#L33

オプション 2 他の Stackoverflow の質問を見ると、リデューサーは状態を変更するものであるべきなので、それをアクションから除外する方が理にかなっていると思います (しかし、これは実際には状態としてカウントされないのでしょうか?): Redux - データを準備する場所

オプション 3 これはミドルウェアの仕事であるという傾向があります。それが 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);
    }

それはうまくいくようです - これは本当にミドルウェアの意図ですか? 元の質問が保持されます-理想的な場所はどこですか?

4

2 に答える 2

14

私に関しては、私はアクションでこの種のことを行います(またはのいずれcoursesLoadedfetchData)。

理由は次のとおりです。

  • これはストア マテリアルではありません。これは単なる外部データ管理であるため、ストアの STATE を変更するはずのレデューサーとは関係ありません。
  • additionalPropertyたとえば、目的を達成するためにすべてを収集する別のレデューサーがあると想像してください。アクションでそれを行うと、正しいデータがすべてのレデューサーに確実に送信されます。
  • これはミドルウェアの典型的な仕事ではありません。これは 1 つのアクションにのみ固有のものですが、ミドルウェアは一連のアクションで同じように使用される場合に役立ちます。さらに、ミドルウェアの使用はよりあいまいであり、リーダーから切り離されます。action-> reducer を使用する方がはるかに簡単で、大きな欠点はありません。
于 2016-03-31T08:32:50.207 に答える