Javascript 如何在 redux 中使用 Immutable.js?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31892767/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 07:20:42  来源:igfitidea点击:

How to use Immutable.js with redux?

javascriptimmutable.jsredux

提问by Gajus

Reduxframework is using reducersto change app state in response to an action.

Redux框架使用reducer来响应一个动作来改变应用程序状态。

The key requirement is that a reducer cannot modify an existing state object; it must produce a new object.

关键要求是 reducer 不能修改现有的 state 对象;它必须产生一个新对象。

Bad Example:

不好的例子

import {
    ACTIVATE_LOCATION
} from './actions';

export let ui = (state = [], action) => {
    switch (action.type) {
        case ACTIVATE_LOCATION:
            state.activeLocationId = action.id;
            break;
    }

    return state;
};

Good Example:

好例子

import {
    ACTIVATE_LOCATION
} from './actions';

export let ui = (state = [], action) => {
    switch (action.type) {
        case ACTIVATE_LOCATION:
            state = Object.assign({}, state, {
                activeLocationId: action.id
            });
            break;
    }

    return state;
};

This is a good use case for Immutable.js.

这是Immutable.js 的一个很好的用例。

采纳答案by Geoffrey Abdallah

Taking your good example with Immutable

以 Immutable 为例

import {
    ACTIVATE_LOCATION
} from './actions';

import { Map } from 'immutable';

const initialState = Map({})

export let ui = (state = initialState, action) => {
  switch (action.type) {
    case ACTIVATE_LOCATION:
      return state.set('activeLocationId', action.id);
    default:
      return state;
  }
};

回答by Gajus

Immutable.js ought to be used in each reducer as needed, e.g.

Immutable.js 应该根据需要在每个 reducer 中使用,例如

import {
    ACTIVATE_LOCATION
} from './actions';

import Immutable from 'immutable';

export let ui = (state, action) => {
    switch (action.type) {
        case ACTIVATE_LOCATION:
            state = Immutable
                .fromJS(state)
                .set('activeLocationId', action.id)
                .toJS();
            break;
    }

    return state;
};

However, there is a lot of overhead in this example: every time reducer action is invoked, it has to convert JavaScript object to an an instance of Immutable, mutate the resulting object and convert it back to JavaScript object.

然而,在这个例子中有很多开销:每次调用 reducer action 时,它必须将 JavaScript 对象转换为 Immutable 的一个实例,改变结果对象并将其转换回 JavaScript 对象。

A better approach is to have the initial state an instance of Immutable:

更好的方法是将初始状态设为 Immutable 的实例:

import {
    ACTIVATE_LOCATION
} from './actions';

import Immutable from 'immutable';

let initialState = Immutable.Map([]);

export let ui = (state = initialState, action) => {
    switch (action.type) {
        case ACTIVATE_LOCATION:
            state = state.set('activeLocationId', action.id);
            break;
    }

    return state;
};

This way, you only need to convert the initial state to an instance of Immutableounce. Then each reducer will treat it as an instance of Immutableand pass it down the line as an instance of Immutable. The catch is that now you need to cast the entire state to JavaScript before passing the values to the view context.

这样,您只需要将初始状态转换为Immutableounce的实例。然后每个reducer 将其视为 的实例并将其作为 的实例Immutable向下传递Immutable。问题是现在你需要在将值传递给视图上下文之前将整个状态转换为 JavaScript。

If you are performing multiple state mutations in a reducer, you might want to consider batching mutationsusing .withMutations.

如果您在减速执行多个状态突变,你可能要考虑配料突变使用.withMutations

To make things simpler, I have developed a redux-immutablelibrary. It provides combineReducersfunction thats equivalent to the function of the same name in the redux package, except that it expect the initial state and all reducers to work with Immutable.jsobject.

为了让事情更简单,我开发了一个redux-immutable库。它提供combineReducers了与 redux 包中的同名函数等价的函数,除了它期望初始状态和所有 reducer 与Immutable.js对象一起工作。

回答by Aaron Jensen

If you're just looking for an easy way to make updates without mutation, I maintain a library: https://github.com/substantial/updeepwhich, in my opinion, is a good way to do that with redux.

如果您只是在寻找一种简单的方法来进行无突变的更新,我会维护一个库:https: //github.com/substantial/updeep,在我看来,这是使用redux.

updeeplets you work with regular (frozen) object hierarchies, so you can do destructuring, see objects in logs and the debugger, etc. It also has a powerful API that allows for batch updating. It's not going to be as efficient as Immutable.js for large data sets because it does clone objects if it needs to.

updeep允许您使用常规(冻结)对象层次结构,因此您可以进行解构、查看日志和调试器中的对象等。它还具有允许批量更新的强大 API。对于大型数据集,它不会像 Immutable.js 那样高效,因为它会在需要时克隆对象。

Here's an example (but check those in the README for more):

这是一个示例(但请查看自述文件中的更多内容):

import {
    ACTIVATE_LOCATION
} from './actions';
import u from 'updeep';

export let ui = (state = [], action) => {
    switch (action.type) {
        case ACTIVATE_LOCATION:
            state = u({ activeLocation: action.id }, state);
            break;
    }

    return state;
};

回答by Michiel

The accepted answer should not be the accepted answer. You need to initialise state using immutable and then (as mentioned before) use redux-immutablejs

接受的答案不应该是接受的答案。您需要使用 immutable 初始化状态,然后(如前所述)使用 redux-immutablejs

const initialState = Immutable.fromJS({}) // or Immutable.Map({})

const store = _createStore(reducers, initialState, compose(
    applyMiddleware(...middleware),
    window.devToolsExtension ? window.devToolsExtension() : f => f
));

Than use the combineReducers from redux-immutablejs

比使用 redux-immutablejs 中的 combineReducers

Extra tip: Using react-router-redux works pretty well so if you would like to add this then replace the reducer from react-router-redux with this:

额外提示:使用 react-router-redux 效果很好,所以如果你想添加这个,那么用这个替换 react-router-redux 中的 reducer:

import Immutable from 'immutable';
import {
    UPDATE_LOCATION
} from 'react-router-redux';

let initialState;

initialState = Immutable.fromJS({
    location: undefined
});

export default (state = initialState, action) => {
    if (action.type === UPDATE_LOCATION) {
        return state.merge({
            location: action.payload
        });
    }

    return state;
};

Just import this into your root reducer

只需将其导入您的根减速器

This is also stated in the documentation of redux-immutablejs

这也在 redux-immutablejs 的文档中有所说明

回答by asaf000

Take a look at https://github.com/indexiatech/redux-immutablejs

看看https://github.com/indexiatech/redux-immutablejs

It's pretty much a combineReducerand an optional createReducerthat conforms with Redux standards.

它几乎是combineReducer一个createReducer符合 Redux 标准的可选项。