immutable保证store state数据不可直接修改

一、作用

新手使用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())

 

 

posted @ 2019-12-23 11:14  盛俊勇  阅读(760)  评论(0编辑  收藏  举报