dagda1 dagda1 - 2 months ago 14
React JSX Question

redux-immutable and initialstate

I am confused as to what is happening with state in my react app that is using redux, redux-immutable and immutablejs.

My reducers looks like this:

export const initialState = Map({
isFetching: false,
forecast: List()
});

export function forecast(state = initialState, action) {
switch(action.type) {
case ActionTypes.FORECAST.REQUEST:
return state.merge({
isFetching: true
});
case ActionTypes.FORECAST.SUCCESS:
return state.merge({
isFetching: false,
forecast: action.response
});
case ActionTypes.FORECAST.FAILURE:
return state.merge({
// isFetching: false
});
}

return state;
};

export function errorMessage(state = null, action) {
const { type, error } = action;

if (type === ActionTypes.RESET_ERROR_MESSAGE) {
return null;
} else if (error) {
return {errorMessage: action.error};
}

return state;
};

export default combineReducers({
forecast,
errorMessage,
routing: routerReducer
});


Here is how I am creating the store:

import reducers from '../reducers';
const initialState = Map();

const store = createStore(reducers,
initialState,
compose(
applyMiddleware(
thunkMiddleware,
logger
)
));


And in a connected component, I am passing this function to connect:

function mapStateToProps(state) {
return {
forecast: state.get('forecast'),
isFetching: state.get('isFetching')
};
}

export default connect(mapStateToProps, {
fetchForecast
})(Forecast);


But if I look at the state that is getting passed into
mapStateToProps


It appears to be a map made up of the 3 reducers I combined with the following code;

export default combineReducers({
forecast,
errorMessage,
routing: routerReducer
});


I could change my code in
mapStateToProps
to this:

function mapStateToProps(state = state.get('forecast')) {
return {
forecast: state.get('forecast').get('forecast'),
isFetching: state.get('forecast').get('isFetching')
};
}


But this feels wrong. Why is my state made up of 3 reducers and not the initial state I specified here:

export const initialState = Map({
isFetching: false,
forecast: List()
});

export function forecast(state = initialState, action) {
switch(action.type) {
case ActionTypes.FORECAST.REQUEST:

Answer

Redux's "combineReducers" method takes multiple slice's of state and combines them into one state. It is working correctly here.

Your initialState is being used within each individual reducer and is setting the initial state of those slices of the overall state. It is not the initial state of the entire combined reducer.

The code you have will create an initial state of:

{
    forecast: {
        isFetching: false,
        forecast: List()
    },
    errorMessage: null,
    routing: //not shown in code provided
}

If, instead, you want forecast to begin with an initial state of "List()" rather than the object, you should change the initial state you pass to the forecast reducer, here;

export function forecast(state = List(), action) {

And then create a separate reducer for "isFetching" if you want it to be a peer of forecast.

Comments