在 react 项目里应用 immutable 对 redux 进行处理,对 List 数据渲染的问题
Posted wertantan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在 react 项目里应用 immutable 对 redux 进行处理,对 List 数据渲染的问题相关的知识,希望对你有一定的参考价值。
一、reducer文件的处理
先安装 immutable 与 redux-immutable
yarn add immutable redux-immutable
安装好后,要在大树下将子树合并,在store文件夹的 reducer.js 文件中引入
import { combineReducers } from ‘redux-immutable‘
import { combineReducers } from ‘redux‘
import { fromJS } from ‘immutable‘
将子树的state 转为 immutable 类型数据
整个是个Map类型,hotCity 是 List 类型
const defaultState = fromJS({ hotCity: [], areas: [], city: ‘全国‘, })
以在城市列表页,以 redux 维护选择的城市这个状态,其所在子树的 reducer.js 文件如import { fromJS } from ‘immutable
import { fromJS } from ‘immutable‘ import { GET_CITYINFO_DATA, CHANGE_CITY_DATA, } from ‘./actionTypes‘ const defaultState = fromJS({ hotCity: [], areas: [], city: ‘全国‘, }) export default (state=defaultState,action) => { if(action.type === GET_CITYINFO_DATA){ // return { // ...state, // hotCity: [...action.result.hotCity], // areas: [...action.result.areas] // } let newList = state.setIn([‘hotCity‘],fromJS(action.result.hotCity)) return newList.setIn([‘areas‘],fromJS(action.result.areas)) //如果要再原来的基础上修改List数据,就要用 updataIn方法如下 插入两个 List // let newList = newProjectInfo.updateIn([‘projectInfo‘],list => list.concat(fromJS(action.result.loadMore),fromJS(action.result.loadMore))) } if(action.type === CHANGE_CITY_DATA){ // return { // ...state, // city: action.city // } return state.setIn([‘city‘],action.city) } return state }
其中注释掉的是不使用 immutable 的代码。第二个 import 引入的是 定义的 action.type 值,可以做到避免在一个大树下有相同的 type 值。其命名如下 :
export const GET_CITYINFO_DATA = ‘address/get_cityInfo_data‘
二、在城市列表页引入 store 内的数据
先引入 connect
import {connect} from ‘react-redux‘
再定义 mapState 与 mapDispatch。
import {CHANGE_CITY_DATA} from ‘pages/address/actionTypes‘ const mapState = (state) => { return { hotCity: state.getIn([‘address‘,‘hotCity‘]), areas: state.getIn([‘address‘,‘areas‘]), } } const mapDispatch = (dispatch) => { return { loadData () { dispatch(loadListAsync(dispatch)) }, changeCity (city) { dispatch({ type: CHANGE_CITY_DATA, city }) } } }
其中 loadData() 方法,请求了数据, changeCity() 方法 改变了所维护的城市状态
loadData() 的相关代码如下:
import { GET_CITYINFO_DATA, } from ‘./actionTypes‘ export const loadCityInfoAsync = (result) => { return { type: GET_CITYINFO_DATA, result } } export const loadListAsync = (dispatch) => { return () => { fetch(‘/api/position/city‘) .then(response => response.json()) .then(result => { dispatch(loadCityInfoAsync(result)) }) } }
三、对数据的渲染
对于 List 类型的数据,利用 map() 进行渲染
代码如下:
import React,{Component} from ‘react‘ import {connect} from ‘react-redux‘ import BScroll from ‘better-scroll‘ import {AddressContainer} from ‘./styledComponents‘ import {loadListAsync} from ‘pages/address/actionCreator‘ import {CHANGE_CITY_DATA} from ‘pages/address/actionTypes‘ const mapState = (state) => { return { hotCity: state.getIn([‘address‘,‘hotCity‘]), areas: state.getIn([‘address‘,‘areas‘]), } } const mapDispatch = (dispatch) => { return { //请求数据 loadData () { dispatch(loadListAsync(dispatch)) }, //改变redux中所保存的城市信息 changeCity (city) { dispatch({ type: CHANGE_CITY_DATA, city }) } } } class AddressContent extends Component { render(){ // 将 this.props 内的内容解构出来 let { hotCity, areas, changeCity, handleClick } = this.props //为在一页显示就没有进一步拆分,看不惯还请见谅 return ( // 绑定 better-scroll 的滚动根元素 <AddressContainer className="address-com-page" ref={el => this.scrollEl = el}> <div> <div> <div className="address-tit">定位城市</div> <div className="address-hot"> <span>定位失败</span> </div> </div> <div> <div className="address-tit" ref="hot">热门城市/区域</div> <div className="address-hot"> { // 对 hotCity 进行渲染,先判断这个数据是否存在,存在再渲染 // 数据是一个 List ,里面是个 Map , 里面的 cities 的值 是一个 List 类型,取得后直接进行map() hotCity.get(0) && hotCity.getIn([0,‘cities‘]).map((v,i) => { return ( // 绑定点击事件,选取所点击的城市 changeCity() // handleClick() 是路由跳转,跳回首页 // cities 的每个子元素都是 Map ,利用 get() 来获取值 <span key={ v.get(‘cityId‘) } onClick={() => { changeCity(v.get(‘name‘)) handleClick() }} > { v.get(‘name‘) }</span> ) }) } </div> </div> <div> { // 对按字母顺序排列的城市列表进行渲染 areas.map((v,i) => { return ( <div key={v.get(‘prefix‘)}> {/* 将小写字母转为大写 */} <div className="address-tit">{ v.get(‘prefix‘).toUpperCase() }</div> <ul className="address-detail"> { // 渲染城市列表,并绑定点击事件 v.get(‘cities‘).map((v,i) => { return ( <li key={v.get(‘cityId‘)} onClick={() => { changeCity(v.get(‘name‘)) handleClick() }}>{ v.get(‘name‘) }</li> ) }) } </ul> </div> ) }) } </div> </div> </AddressContainer> ) } componentDidMount(){ // 调用 mapDispatch 中的loadData() 方法,获取数据 this.props.loadData() this.bScroll = new BScroll(this.scrollEl,{ click: true, }) } } export default connect(mapState,mapDispatch)(AddressContent)
至此城市列表页就渲染出来了。
以上就是利用 immutable 处理 redux 的 过程!
如果有问题,欢迎指出。
以上是关于在 react 项目里应用 immutable 对 redux 进行处理,对 List 数据渲染的问题的主要内容,如果未能解决你的问题,请参考以下文章
Immutable.js 以及在 react+redux 项目中的实践
Immutable.js 与 React Typescript 结合
是否可以在 React-Redux 应用程序中使用 Immutable.js 来比较 shouldComponentUpdate 中的道具?