immutable
2022-03-31 本文已影响0人
泡杯感冒灵
我们知道,在我们使用reducer时,这个函数接收了原始的state作为参数,并且一定不能对这个state进行修改,需要返回一个新的state回去。想要做到这一点,就需要我们时刻警惕保持编码习惯,不去修改state,但是就怕不小心改了,代码会出现异常,而且找不到出错的地方。那么有没有办法把state变为一个不可以被改变的对象,这样我们就不用时刻担心不小心修改了state了。这个时候,我们需要借助immutable.js
这个第三方模块。
immutable.js
是一个第三方模块,是facebook团队历时3年开发的,它可以帮助我们生成一个immutable对象,这个对象是不可被改变的
。
- 安装
npm install immutable / yarn add immutable
- 引入方法
fromJS
,它可以把一个JS对象变为immutable对象。
import { fromJS } from 'immutable';
const defaultState = fromJS({
focused:false
});
- 当我们在reducer里把state转为immutable对象后,再通过state.header.focused这种方法去访问focused这个属性,是不行的。
// 转immutable对象之前
const mapStateToProps = (state) => {
return {
focused:state.header.focused
};
}
// 转immutable对象之后,通过immutable对象的get方法来访问属性
const mapStateToProps = (state) => {
return {
focused:state.header.get('focused')
};
}
- 同时,当派发了action后,reducer去修改数据的时候,因为state已经变为了immutable对象,这个时候需要借助immutable对象的set方法去修改
export default (state = defaultState,action) => {
if(action.type === constants.SEARCH_FOCUS){
return state.set('focused',true);
// return {
// focuesd:true
// };
}
if(action.type === constants.SEARCH_BLUR){
return state.set('focused',false);
// return {
// focuesd:false
// };
}
return state
}
- 表面看set方法是把state对象修改了,但是实际上它的的逻辑是,会结合之前
immutable对象的值
和设置的值
,返回一个全新的对象
。并没有对原来的数据进行修改。
总之,如果不借助immutable对象,我们需要借助手动的方法保证state不被修改,这是存在风险的。当我们引入了immutable对象后,数据就不会被直接的被访问和修改了。而是要通过get和set方法去访问和修改。并没有改变原始的state的内容。
注意,当我们通过state.header.get('focused')访问 focused的时候,state还是一个JS对象,而header才是immutable对象,这个时候,我们需要把state也转为immutable对象,这个时候需要借助 redux-immutable
这个第三方工具。
- 先安装
npm install redux-immutable
- 再引入
// 之前我们通过combineReducers 方法去把小的reducer合并为一个reducer
import { combineReducers } from 'redux';
// 现在 我们通过引入 redux-immutable的combineReducers 方法,来合并的同时,把传入的对象转为 immutable对象
import { combineReducers } from 'redux-immutable';
const reducer = combineReducers({
header:headerReducer
})
- 当state也转为immutable对象对象后,我们再访问header就不能直接 state.header了 ,需要通过 immutable对象的get方法
const mapStateToProps = (state) => {
return {
focused:state.get('header').get('focused')
};
}
// 还有其他写法,通过`getIn()方法`,该方法接收一个数组
const mapStateToProps = (state) => {
return {
// 意思是,取header下边的focused的值
focused:state.getIn(['header','focused'])
// focused:state.get('header').get('focused')
};
}