一、作用
新手使用state时候,容易错误的直接更改state数据,在redux中这是不被允许的。Immutable 来解决这个问题。
Immutable Data 就是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。
二、immutable在react中的使用
- 安装
-
npm install immutable
第二步:在reducer.js中,将数据转成immutable,返回数据也返回一个Immutable对象,
该对象中有searchFocused数据
-
import * as constants from './constants' import {fromJS} from 'immutable' // const defaultState = { // searchFocused: false // } const defaultState = fromJS({ searchFocused: false }) export default (state=defaultState,action) => { if(action.type === constants.SEARCH_FOCUS){ // return { // searchFocused: true // } // set是返回了一个全新的对象(这个对象里面的数据是之前对象的数据和现在更改的结合),但是没有更改原来对象的数据 return state.set('searchFocused',true) } if(action.type === constants.SEARCH_BLUR){ // return { // searchFocused: false // } return state.set('searchFocused',false) } return state }
第三步:使用的时候,不能直接state点下面的属性,因为返回得到是一个Immutable对象,要获取数据得用get方法
-
const mapStateToProps = (state) => { return { // searchFocused: state.header.searchFocused searchFocused: state.header.get("searchFocused") } }
第四步:使用redux-immutable来统一数据格式
上面代码中,state还不是一个immutable对象,stata.header又是一个immutable对象,这样数据格式不统一,容易写错,最好是state也是immutable对象
写成下面这样统一数据
state.get("header").get("searchFocused")
如何把state也转成state对象,就需要在主store的reducer.js中,将combineReducers方法从redux-immutable中导入,而不是从redux中导入,这样reducer返回的state就是immutable对象了。
先npm i redux-immutable
在项目更目录的store文件夹下的reducer.js中:
// import {combineReducers} from 'redux' import {combineReducers} from 'redux-immutable' import {reducer as headerReducer} from '../common/header/store' const reducer = combineReducers({ // 给这个分支 header: headerReducer }) export default reducer
此时组件组获取数据,就可以写成如下方式了
const mapStateToProps = (state) => { return { // searchFocused: state.header.searchFocused searchFocused: state.get("header").get("searchFocused") } }
immutable还挺提供了其他api,也可以这么写:
//searchFocused: state.get("header").get("searchFocused") searchFocused: state.getIn(["header","searchFocused"])
注意点:
当属性是一个复杂类型时候,fromJS同样会把其转成immutable对象
const defaultState = fromJS({ searchFocused: false,
// 这也变成immutable对象 searchList: [] })
所以当我们获取服务器数据,并构造一个action的时候,就把aciton要传递的数据改成immutable对象,否则会造成数据格式不统一
const changeList = (data) => ({ type:constants.CHANGE_LIST, data: fromJS(data) }) export const getList = () => { return (dispatch) => { axios.get('/api/headerList.json').then(res=>{ const data = res.data dispatch(changeList(data.data)) }).catch(()=>{ console.log("error") }) }
immutable对象也提供了map方法,可以按照数组方式去遍历searchList
{searchList.map(item=>(
<SearchInfoItem key={item}>{item}</SearchInfoItem>
))}
immutable对象没有length属性,获取数组长度方法是size
searchList.size === 0 && dispatch(actionCreators.getList())