React Redux:在 Reduce 状态下使用不可变

Posted

技术标签:

【中文标题】React Redux:在 Reduce 状态下使用不可变【英文标题】:React Redux: Using Immutable in Reduce State 【发布时间】:2018-06-23 12:51:23 【问题描述】:

我正在学习 Immutable.js,但我很难在 reducer 中处理 Immutable.js。 我已经像这样声明了我的 initialState:

import  fromJS  from 'immutable';

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

我正在尝试修改 initialState,但出现错误:“state.setIn 不是函数”。

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

在 index.js 中,我将默认状态声明为不可变 Map() 对象:

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

在 combineReducers 中,我使用的是“redux-immutable”。

import  combineReducers  from 'redux-immutable';  

用 Immutable.js 修改 reducer 状态的正确方法是什么?

【问题讨论】:

【参考方案1】:

toJS 和 fromJS 是昂贵的操作。 您不应该使用 initial_state 或 state 的 fromJS。

我建议你在你的 users reducer 上这样做以获得更好的性能并且不要处理 toJS 和 fromJS。并且还在您的代码(选择器、组件、视图)中使用 get 来检索任何值。

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; 

请不要在创建 Store 时使用 immutable。您不需要任何不可变的操作,因为它假定商店是不可变的。 所以 Immutable 应该是 reducer 中的任何数据结构。

这是一个常见的配置存储文件(或您的情况下的索引)的示例:

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;

在文件 state/reducers 中,您拥有不同实体的所有 reducer:

import  combineReducers  from 'redux';
import users from './users';

const ownReducers = ;

const appReducer = combineReducers(
  ...ownReducers,
  // add here your reducers after importing the entity state
  // i.e: myStuff: myStuff.reducer, etc...
  users: claims.reducer,
);

const rootReducer = (state, action) => 
  return appReducer(state, action);
;

export default rootReducer;

最好的!

【讨论】:

【参考方案2】:

我假设在 reducer 中返回的 state 不是不可变映射。据我所知,您只是通过使用 fromJS(...) 将初始状态转换为不可变映射,您可以尝试在减速器中做同样的事情。

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

但我建议您查看this documentation,因为它针对您的需求。

【讨论】:

以上是关于React Redux:在 Reduce 状态下使用不可变的主要内容,如果未能解决你的问题,请参考以下文章

总结下Redux

总结下Redux

React Redux 服务器渲染但客户端获取数据

如何在不改变状态的情况下对 redux 操作做出反应

auto-redux,跟普通hooks一样使用redux。

在 Redux 中没有 React Navigation 状态的 React Native 中的 Redux