Redux 和 immutable js,我在尝试使用 immutable 后失去了状态
Redux and immutable js, I lost my state after trying to use immutable
在开始使用 reactjs 和 redux 进行开发后,我认为在使用 redux 的同时使用 immutable.js 会更好。
但是...可能是我智障还是需要一些练习才能正确使用它,一切都崩溃了。
如果您能帮助理解这里出了什么问题,那就太棒了!
所以,这是我的第一个代码:
export function posts(state = {
isFetching: true,
didInvalidate: false,
items: []
}, action) {
switch (action.type) {
case INVALIDATE_REQ:
return Object.assign({}, state, {
didInvalidate: true
});
case REQUEST_POSTS:
return Object.assign({}, state, {
isFetching: true,
didInvalidate: false
});
case RECEIVE_POSTS:
return Object.assign({}, state, {
isFetching: false,
didInvalidate: false,
items: action.posts
});
default:
return state;
};
};
我是这样改造的:
const initPostState = Map({
isFetching: true,
didInvalidate: false,
items: []
});
export function posts(state = initPostState, action) {
switch (action.type) {
case INVALIDATE_REQ:
return state.set('didInvalidate', true);
case REQUEST_POSTS:
return state.set({
isFetching: true,
didInvalidate: false
});
case RECEIVE_POSTS:
return state.set({
isFetching: false,
didInvalidate: false,
items: action.posts
});
default:
return state;
};
};
我的容器 MapStateToProps:
function mapStateToProps(state) {
const {
posts: isFetching,
posts
} = state.posts;
console.log(state);
...
所以问题是,我如何访问我的状态?
状态控制台报告:
我迷路了!求助!
如果您将 ImmutableJS 与 redux 一起使用,那么您的整个应用程序状态都是不可变的。在connect
函数中,使用state.get("posts")访问posts
状态。然后您将不得不使用 get()
访问 posts
状态属性。或者您可以使用 toJs() 来避免必须在组件内部操作不可变。
您需要使用 immutableJS 中的 get
方法
使用 state.get('didInvalidate')
访问 didInvalidate
的值,对于其他值也是如此。
如果您使用的是 javascript 对象,那么您可以像 state.get('something').toJS()
这样做应该会给你灵感
function mapStateToProps(state){
const isFetching = state.get('isFetching'),
const items = state.get('items').toJS();
}
切勿在 mapStateToProps
中使用 toJS()
。来自 Redux 文档:
Converting an Immutable.JS object to a JavaScript object using toJS()
will return a new object every time. If you do this in mapSateToProps
, you will cause the component to believe that the object has changed every time the state tree changes, and so trigger an unnecessary re-render.
如果您的应用需要高性能,您必须在 Dumb 组件中使用 Immutable.js 及其 get()
和 getIn()
助手。
Also since ImmutableJS has versatile API, in most cases it removes the
need for helper libraries like lodash.
但在大多数情况下,您可以使用他们建议的代码通过牺牲性能将 Immutable.js 与您的组件分开。
一个 HOC 组件(最新的 immutable.js 使用 isIterable 谓词):
import React from 'react';
import { Iterable } from 'immutable';
export const toJS = (WrappedComponent) =>
(wrappedComponentProps) => {
const KEY = 0;
const VALUE = 1;
const propsJS = Object.entries(wrappedComponentProps)
.reduce((newProps, wrappedComponentProp) => {
newProps[wrappedComponentProp[KEY]] =
Iterable.isIterable(wrappedComponentProp[VALUE])
? wrappedComponentProp[VALUE].toJS()
: wrappedComponentProp[VALUE];
return newProps;
}, {});
return <WrappedComponent {...propsJS} />
};
一个 HOC 组件(最新的 immutable.js 使用 isImmutable 谓词):
import React from 'react';
import { isImmutable } from 'immutable';
export const toJS = (WrappedComponent) =>
(wrappedComponentProps) => {
const KEY = 0;
const VALUE = 1;
const propsJS = Object.entries(wrappedComponentProps)
.reduce((newProps, wrappedComponentProp) => {
newProps[wrappedComponentProp[KEY]] =
isImmutable(wrappedComponentProp[VALUE])
? wrappedComponentProp[VALUE].toJS()
: wrappedComponentProp[VALUE];
return newProps;
}, {});
return <WrappedComponent {...propsJS} />
};
使用方法:
import { connect } from 'react-redux';
import { toJS } from './to-js';
import DumbComponent from './dumb.component';
const mapStateToProps = (state) => {
return {
/**
obj is an Immutable object in Smart Component, but it’s converted to a plain
JavaScript object by toJS, and so passed to DumbComponent as a pure JavaScript
object. Because it’s still an Immutable.JS object here in mapStateToProps, though,
there is no issue with errant re-renderings.
*/
obj: getImmutableObjectFromStateTree(state)
}
};
export default connect(mapStateToProps)(toJS(DumbComponent));
在 Redux immutable-js-best-practices 文档部分有很多链接可以继续。
在开始使用 reactjs 和 redux 进行开发后,我认为在使用 redux 的同时使用 immutable.js 会更好。
但是...可能是我智障还是需要一些练习才能正确使用它,一切都崩溃了。
如果您能帮助理解这里出了什么问题,那就太棒了!
所以,这是我的第一个代码:
export function posts(state = {
isFetching: true,
didInvalidate: false,
items: []
}, action) {
switch (action.type) {
case INVALIDATE_REQ:
return Object.assign({}, state, {
didInvalidate: true
});
case REQUEST_POSTS:
return Object.assign({}, state, {
isFetching: true,
didInvalidate: false
});
case RECEIVE_POSTS:
return Object.assign({}, state, {
isFetching: false,
didInvalidate: false,
items: action.posts
});
default:
return state;
};
};
我是这样改造的:
const initPostState = Map({
isFetching: true,
didInvalidate: false,
items: []
});
export function posts(state = initPostState, action) {
switch (action.type) {
case INVALIDATE_REQ:
return state.set('didInvalidate', true);
case REQUEST_POSTS:
return state.set({
isFetching: true,
didInvalidate: false
});
case RECEIVE_POSTS:
return state.set({
isFetching: false,
didInvalidate: false,
items: action.posts
});
default:
return state;
};
};
我的容器 MapStateToProps:
function mapStateToProps(state) {
const {
posts: isFetching,
posts
} = state.posts;
console.log(state);
...
所以问题是,我如何访问我的状态? 状态控制台报告:
我迷路了!求助!
如果您将 ImmutableJS 与 redux 一起使用,那么您的整个应用程序状态都是不可变的。在connect
函数中,使用state.get("posts")访问posts
状态。然后您将不得不使用 get()
访问 posts
状态属性。或者您可以使用 toJs() 来避免必须在组件内部操作不可变。
您需要使用 immutableJS 中的 get
方法
使用 state.get('didInvalidate')
访问 didInvalidate
的值,对于其他值也是如此。
如果您使用的是 javascript 对象,那么您可以像 state.get('something').toJS()
这样做应该会给你灵感
function mapStateToProps(state){
const isFetching = state.get('isFetching'),
const items = state.get('items').toJS();
}
切勿在 mapStateToProps
中使用 toJS()
。来自 Redux 文档:
Converting an Immutable.JS object to a JavaScript object using
toJS()
will return a new object every time. If you do this inmapSateToProps
, you will cause the component to believe that the object has changed every time the state tree changes, and so trigger an unnecessary re-render.
如果您的应用需要高性能,您必须在 Dumb 组件中使用 Immutable.js 及其 get()
和 getIn()
助手。
Also since ImmutableJS has versatile API, in most cases it removes the need for helper libraries like lodash.
但在大多数情况下,您可以使用他们建议的代码通过牺牲性能将 Immutable.js 与您的组件分开。
一个 HOC 组件(最新的 immutable.js 使用 isIterable 谓词):
import React from 'react';
import { Iterable } from 'immutable';
export const toJS = (WrappedComponent) =>
(wrappedComponentProps) => {
const KEY = 0;
const VALUE = 1;
const propsJS = Object.entries(wrappedComponentProps)
.reduce((newProps, wrappedComponentProp) => {
newProps[wrappedComponentProp[KEY]] =
Iterable.isIterable(wrappedComponentProp[VALUE])
? wrappedComponentProp[VALUE].toJS()
: wrappedComponentProp[VALUE];
return newProps;
}, {});
return <WrappedComponent {...propsJS} />
};
一个 HOC 组件(最新的 immutable.js 使用 isImmutable 谓词):
import React from 'react';
import { isImmutable } from 'immutable';
export const toJS = (WrappedComponent) =>
(wrappedComponentProps) => {
const KEY = 0;
const VALUE = 1;
const propsJS = Object.entries(wrappedComponentProps)
.reduce((newProps, wrappedComponentProp) => {
newProps[wrappedComponentProp[KEY]] =
isImmutable(wrappedComponentProp[VALUE])
? wrappedComponentProp[VALUE].toJS()
: wrappedComponentProp[VALUE];
return newProps;
}, {});
return <WrappedComponent {...propsJS} />
};
使用方法:
import { connect } from 'react-redux';
import { toJS } from './to-js';
import DumbComponent from './dumb.component';
const mapStateToProps = (state) => {
return {
/**
obj is an Immutable object in Smart Component, but it’s converted to a plain
JavaScript object by toJS, and so passed to DumbComponent as a pure JavaScript
object. Because it’s still an Immutable.JS object here in mapStateToProps, though,
there is no issue with errant re-renderings.
*/
obj: getImmutableObjectFromStateTree(state)
}
};
export default connect(mapStateToProps)(toJS(DumbComponent));
在 Redux immutable-js-best-practices 文档部分有很多链接可以继续。