一、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. RabbitMQ(三):RabbitMQ与Spring Boot简单整合

    RabbitMQ是目前非常热门的一款消息中间件,不管是互联网大厂还是中小企业都在大量使用.Spring Boot的兴起,极大地简化了Spring的开发,本文将使用Spring Boot与RabbitM ...

  2. Python(简单图形和文件处理)编程

    Python确实是一门很简洁而且功能有强大的语言,我觉得开始学习很容易理解,说到熟练和精通还是不容易的,还需不断学习. 从最基础的语法学习,有些部分各种语言是相同的,让人很好理解.编程也是从最简单语法 ...

  3. 【iOS】libc++abi.dylib: terminate_handler unexpectedly threw an exception

    用 ShareSDK 做第三方分享的时候遇到了这个问题…… 联系了客服,后来在他的指导下,发现是数组的问题,该问题不知道是否具有通用性,暂且记下.

  4. 【iOS】Your account already has a valid ios

    打包内测的时候遇到了这个问题,如图所示: 官网解决办法: If the certificate already exists in Member Center, a “Your account alr ...

  5. Struts2 中Struts.xml结果页面配置

    结果页面的配置: 红色的比较常用 

  6. Filebeat6.3文档—Log input配置

    Filebeat6.3文档-Log input配置 paths 日志加载的路径.例如加载某一子目录级别下面路径的日志:/var/log/*/*.log.这表示会去加载以.log结尾的/var/log下 ...

  7. Java Lambda表达式forEach无法跳出循环的解决思路

    Java Lambda表达式forEach无法跳出循环的解决思路 如果你使用过forEach方法来遍历集合,你会发现在lambda表达式中的return并不会终止循环,这是由于lambda的底层实现导 ...

  8. java并发编程(二十二)----(JUC集合)ConcurrentHashMap介绍

    这一节我们来看一下并发的Map,ConcurrentHashMap和ConcurrentSkipListMap.ConcurrentHashMap通常只被看做并发效率更高的Map,用来替换其他线程安全 ...

  9. 常用maven 命令

    重新依赖:mvn package -U -DskipTest=true; 在本地安装jar包:mvn install 清除产生的项目:mvn clean 运行测试:mvn test 上传到私服:mvn ...

  10. Springboot 优雅停止服务的几种方法

    在使用Springboot的时候,都要涉及到服务的停止和启动,当我们停止服务的时候,很多时候大家都是kill -9 直接把程序进程杀掉,这样程序不会执行优雅的关闭.而且一些没有执行完的程序就会直接退出 ...