一、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. thinkphp 数据库操作

    //所有的数据中,查出某个字段$result = $music->field('music')->select();$hotlist = M('News')->where('stat ...

  2. 深入理解Java中的锁(三)

    ReadWriteLock接口 读写锁维护一对关联锁,一个只用于读操作,一个只用于写操作.读锁可以由多个线程同时持有,又称共享锁.写锁同一时间只能由一个线程持有,又称互斥锁.同一时间,两把锁不能被不同 ...

  3. 微信小程序登陆流程图时序图

    微信小程序登录 小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系. 微信小程序登录流程时序图 说明 调用 wx.login() 获取 临时登录凭证cod ...

  4. istio使用教程

    kubernetes各版本离线安装包 安装 安装k8s 强势插播广告 三步安装,不多说 安装helm, 推荐生产环境用helm安装,可以调参 release地址 如我使用的2.9.1版本 yum in ...

  5. 【Spring】No converter found for return value of type: class java.util.ArrayList

    错误信息: org.springframework.http.converter.HttpMessageNotWritableException: No converter found for ret ...

  6. python 实现两个文本文件内容去重

    实现两个文本内容去重,输出两个文本不重复的结果 两个测试文本内容如下 1.txt中内容为 1 2 3 4 5 6 7 8 2.txt中内容为 1 2 3 4 5 6 7 8 9 10 11 12 13 ...

  7. .NET中的值类型与引用类型

    .NET中的值类型与引用类型 这是一个常见面试题,值类型(Value Type)和引用类型(Reference Type)有什么区别?他们性能方面有什么区别? TL;DR(先看结论) 值类型 引用类型 ...

  8. S2:面向对象

    面向对象七大设计原则 1. 开闭原则 2. 里氏替换原则 3. 单一职责原则 4. 接口隔离原则 5. 依赖倒置原则 6. 迪米特原则 7.组合/聚合复用原则 原则一:(SRP:Single resp ...

  9. codeforces1088D_Ehab and another another xor problem交互题

    传送门 一道考验思维的交互题 大致思路就是从最高的二进制位向下询问 代入例子比如: 5 6 6 5 7 4 6 4 讨论一下 交互题的重点学会推理和归纳 #include <bits/stdc+ ...

  10. MyBatis之#{} and ${}

    #{} 和 ${} 之间最大的差别就是  #{}会在使用的时候被加上 ‘’ 引号, ${}直接传值,不做任何处理 1.#{}对传入的参数会做预编译,也就是会当做字符串来处理 select * from ...