Using a combination of React, Redux and Thunk, I have the following:
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));
});
};
}
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;
The two snippets above sit well, and i feel like they align to the intentions of Redux. I want to now do some modifications to the fields that are returned in the response, before they hit the containers.
For example, the response might be:
[
{ code: "R101", name: "Intro to Redux", author: "Dan" },
{ code: "R102", name: "Middleware", author: "Dan" },
]
And I want to change it to (simple example for simplicity):
[
{ code: "R101", name: "Intro to Redux", author: "Dan", additionalProperty: "r101_intro_to_redux" },
{ code: "R102", name: "Middleware", author: "Dan", additionalProperty: "r102_middleware" },
]
Research thus far
Option One Looking at the async example on Redux, I can see there is a light touch to the response here: https://github.com/reactjs/redux/blob/master/examples/async/actions/index.js#L33
Option Two Looking at other Stackoverflow questions, it leads me to believe keeping it out of the actions makes more sense, as reducers should be what modifies state (but perhaps this doesn't really count as state?): Redux - where to prepare data
Option Three I have an inclining that this is the job of middleware - being that's how normalizr handles it, but I can't find any non-passive middleware examples. If middleware is the go here, should the middleware be dispatching some kind of SET_STATE action, or is it free to update state right there in the middleware?
EDIT
Experimented with some middleware, such as:
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);
}
It seems to work fine - is this indeed the intention of middleware? Original question holds - where it the ideal spot?
As for me I do this kind of things in the action (either coursesLoaded
or fetchData
).
Here are the reasons why:
additionalProperty
for achiving purposes for example, so doing it in the action ensures that the right data is sent to all reducers.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With