简体   繁体   中英

React Redux: Using Immutable in Reduce State

I'm learning Immutable.js, but I'm having difficulty to handle with Immutable.js in reducers.
I've declared my initialState like this:

import { fromJS } from 'immutable';

const INITIAL_STATE = fromJS({
  users: {
    isLoading: false,
    items: []
  }
});  

I'm trying to modify the initialState but I'm getting an error: "state.setIn is not a function".

case 'FETCH_USERS_SUCCESS':
      return state
        .setIn(['users', 'isLoading'], false)
        .setIn(['users', 'items'], action.users)

In the index.js, I'm declaring the deafult state as a Immutable Map() object:

let store = createStore(..., Map({}), composeEnhancers(...));

And in the combineReducers I'm using the 'redux-immutable'.

import { combineReducers } from 'redux-immutable';  

What is the right way to modify the reducer state with Immutable.js?

toJS and fromJS are expensive operations. You shouldn't do a fromJS of the either initial_state or state.

I suggest you to do this at your users reducer to have better performance and don't deal with toJS and fromJS. And also use in your code (selectors, components, views) a get to retrieve any value.

 import { List as ImmutableList, Map as ImmutableMap } from 'immutable'; import { FETCH_USERS_SUCCESS } from './constants'; // or whatever you have your constants file const initialState = new ImmutableMap({ isLoading: false, items: new ImmutableList([]); }); function users(state = initialState, action) { switch (action.type): case FETCH_USERS_SUCCESS: return state.merge({ isFetching: false, users: action.users }); default: return state; } 

Please, don't use immutable when creating the Store. You don't need there any immutable action since it's supposed the store is immutable. So Immutable should be any data structure inside your reducer.

This is an example of a common configure-store file (or index in your case):

 import { applyMiddleware, createStore } from 'redux'; import { composeWithDevTools } from 'redux-devtools-extension'; import thunk from 'redux-thunk'; import rootReducer from 'state/reducers'; export default function configureStore(initialState = {}) { const store = createStore( rootReducer, initialState, composeWithDevTools(applyMiddleware(thunk)), ); // to query state in the console window.appState = store.getState(); if (module.hot) { const nextReducer = require('state/reducers'); module.hot.accept('state/reducers', () => { store.replaceReducer(nextReducer); }); } return store; } 

And in the file state/reducers you have all the reducers of the different entities:

 import { combineReducers } from 'redux'; import users from './users'; const ownReducers = {}; const appReducer = combineReducers({ ...ownReducers, // add here your reducers after importing the entity state // ie: myStuff: myStuff.reducer, etc... users: claims.reducer, }); const rootReducer = (state, action) => { return appReducer(state, action); }; export default rootReducer; 

Best!

I assume that the state being returned within the reducer is not an immutable map. As far as I can see, you are just converting your initial state to an immutable map by using fromJS(...) , you could try to do the same thing within your reducer.

return fromJS(state)
        .setIn(.setIn(['users', 'isLoading'], false)
        .setIn(['users', 'items'], fromJS(action.users))

But I'd recommend to take a look at this documentation , since it targets your demands.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM