一、reducer文件的处理

先安装 immutable 与 redux-immutable

yarn add immutable redux-immutable

我们可能会在很多地方定义子树,这就需要在大树下将它们合并,在store文件夹的 reducer.js 文件中引入

import { combineReducers } from 'redux-immutable'
取代原本的
import { combineReducers } from 'redux'
将子树合并为一个大树。
export default combineReducers({
homepage,
address,
})

在每一个子树的 reducer.js 文件中引入 fromJS
import { fromJS } from 'immutable'

将子树的state 转为 immutable 类型数据

整个 defaultState 是个Map类型,hotCity 是 List 类型

const defaultState = fromJS({
hotCity: [],
areas: [],
city: '全国',
})

以在城市列表页,以 redux 维护选择的城市这个状态,其所在子树的 reducer.js 文件引入 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() 方法是异步的请求数据,如果要想异步的请求数据则需要引入 中间件,这里用的是 redux-thunk ,同时需要引入 redux 的 applyMiddleware ,将中间件加上

import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk' import reducers from './reducers' const store = createStore(reducers,applyMiddleware(thunk)) export default store //这是 store 文件夹下的 index.js 文件,暴露 store

这时就可以在action时异步的请求数据,redux-thunk会检测dispatch的内容,如果是个对象就直接让其正常向后执行,如果是函数,则会在函数执行完后,再次dispatch再正常后流。

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中使用的更多相关文章

  1. 搭建React项目(一):在网页中使用

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. 在react项目中使用redux-thunk,react-redux,redux;使用总结

    先看是什么,再看怎么用: redux-thunk是一个redux的中间件,用来处理redux中的复杂逻辑,比如异步请求: redux-thunk中间件可以让action创建函数先不返回一个action ...

  3. React项目中实现右键自定义菜单

    最近在react项目中需要实现一个,右键自定义菜单功能.找了找发现纯react项目里没有什么工具可以实现这样的功能,所以在网上搜了搜相关资料.下面我会附上完整的组件代码. (注:以下代码非本人原创,具 ...

  4. React项目实战:react-redux-router基本原理

    React相关 React 是一个采用声明式,高效而且灵活的用来构建用户界面的框架. JSX 本质上来讲,JSX 只是为React.createElement(component, props, .. ...

  5. react项目结合echarts,百度地图实现热力图

    一.最近在一个react项目(antd pro)中需要展示一个热力地图.需求是: 1.热力地图可缩放: 2.鼠标点击可以展示该点地理坐标,及热力值. 3.初始化时候自适应展示所有的热力点. 4.展示热 ...

  6. React 项目引入 Dva

    背景 现在手上在做的 React 项目因为年代久远,用的 Redux,写代码的体验不太好,所以想升级一下引入 dva.以往使用 dva 都是使用 dva-cli 直接生成 dva 项目,或者在使用 a ...

  7. 使用Facebook的create-react-app脚手架快速构建React开发环境(ant.design,redux......)

    编程领域中的“脚手架(Scaffolding)”指的是能够快速搭建项目“骨架”的一类工具.例如大多数的React项目都有src,public,webpack配置文件等等,而src目录中又包含compo ...

  8. 【Webpack2.X笔记】 配合react项目进行配置

    前言: 本文是自己在工作中使用webpack进行react开发项目构建的一些经验总结,做以记录防范后续踩坑. 如果您还没有webpack相关基础,请先移步 入门Webpack,看这篇就够了 进行基础学 ...

  9. React项目的最佳实践

    项目代码 从零开始简书项目 ​ 从我第一次接触vue这个框架已经过了快一年的时间,陪伴我从前端小白到前端工程师,前端时间也是使用了 ts+vue这样的组合写代码,明显感觉vue与ts似乎没有产生比较好 ...

随机推荐

  1. TreeSet类的排序

    TreeSet支持两种排序方法:自然排序和定制排序.TreeSet默认采用自然排序. 1.自然排序 TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间大小关系, ...

  2. HTTP_4_返回结果的HTTP状态码

    状态码:返回请求结果. 状态码种类繁多,以下总结常用的状态码:     类别 信息性状态码 1XX 服务器接受请求,继续处理       成功状态码 200 OK 请求处理成功,并返回资源(响应报文中 ...

  3. 金蝶K3 V12.2版本,对已发生业务单据的物料启用辅助计量单位

    /****************************************************************************** 联达双计量单位 yLD_K3Data_S ...

  4. 【iOS】iOS 调试快速定位程序在哪崩溃

    iOS 开发过程中经常遇到程序崩溃.快速定位程序在哪崩溃的步骤如下: 1. 2. 3. 这样设置后,程序崩溃时会定位到崩溃的语句,如下: 原文链接:iOS开发何如在调试的时候轻松找到程序在哪里崩溃

  5. SpringBoot Jar包瘦身 - 跟大文件说再见!

    前言 SpringBoot部署起来配置非常少,如果服务器部署在公司内网,上传速度还行,但是如果部署在公网(阿里云等云服务器上),部署起来实在头疼.就是 编译出来的 Jar 包很大,如果工程引入了许多开 ...

  6. 【POJ - 2456】Aggressive cows(二分)

    Aggressive cows 直接上中文了 Descriptions 农夫 John 建造了一座很长的畜栏,它包括N (2 <= N <= 100,000)个隔间,这些小隔间依次编号为x ...

  7. (转)Linux LVM逻辑卷配置过程详解(创建、扩展、缩减、删除、卸载、快照创建)

    一.预备知识 LVM全称为Logical Volume Manager 逻辑卷管理器,LVM是Linux环境中对磁盘分区进行管理的一种机制,是建立在硬盘和分区之上.文件系统之下的一个逻辑层,可提高磁盘 ...

  8. Docker入门学习笔记

    Docker 什么是Docker 虚拟化技术 在计算机中,虚拟化是一种资源管理技术,将计算机中的各种实体资源如:CPU.硬盘.内存等予以抽象.转换后呈现出来打破实体结构间的不可切割的障碍,使用户可以比 ...

  9. 【一些小常识】Linux文件目录的通配符用法/*

    在使用linux命令的时候,一时有点搞不清*的用法,于是整理记录下,在做jenkins 持续集成时还是很有用的 “*”在通配符中是最常用的一种,主要整理下在使用Linux命令时,文件夹目录的用法. 1 ...

  10. DevOps实施历程-v1.0

    ​    有AF项目的成功案例(DevOps实施历程-半自动化),公司新项目全部依此为模板,实现了从代码到安装的自动化流水线,为此我输出了Jenkins自动化指南.AF项目指南等文档,方便大家查阅和参 ...