在一个大项目中如何引入redux及其相关技术栈(react-redux redux-thunk redux-immutable ),已经成为react前端工程师不可或缺的技能,下面通过实现一个简单的todolist效果,来介绍相关流程

1.引入redux进行应用数据管理,安装相关依赖

yarn add redux  react-redux redux-thunk redux-devtools-extension
一般目录结构

2.创建好store.js、reducer.js、action.js、action-types.js

1)store.js
 /*
redux最核心的管理对象store
*/
import {createStore} from 'redux'
import reducer from './reducer' const store = createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
// 向外默认暴露store
export default store

2) reducer.js

 import {CHANGEINPUT,ADDITEMS } from './action-types'

 const defalutState = {
inputValue : 'wuxiaohui',
list :[]
} export default (state = defalutState,action) =>{
if(action.type === CHANGEINPUT){
let newState = JSON.parse(JSON.stringify(state))//深拷贝
newState.inputValue = action.value
return newState
}
if(action.type === ADDITEMS){
let newState = JSON.parse(JSON.stringify(state))
newState.list.push(newState.inputValue)
newState.inputValue = ''
return newState
} return state
}

3)action.js

import {CHANGEINPUT,ADDITEMS } from './action-types'

export const inputChange = (e)=>({
type:CHANGEINPUT,
value:e.target.value
}) export const clickButton = ()=>({
type:ADDITEMS
})

4)action-types.js

/*
包含n个action type常量名称的模块
*/
export const CHANGEINPUT = 'change_input'
export const ADDITEMS = 'add_item'

3.创建todolistui组件

编写TodolistUI.js,由于没有双向绑定,通过onChange的inputChange事件拿到输入值并通过inputValue传回给输入框,clickButton则是向list中追加输入框中输入的数据,输入后清空。该逻辑在 reducer.js中体现,UI组件只负责展示。
 
//把TodoList改为UI组件-提高性能

import React from "react";

 const TodoListUI =(props)=>{
// 接收connect连接器映射传递的属性和函数
let {inputValue ,inputChange,clickButton,list} = props;
return ( <div>
<div>
<input value={inputValue} onChange={inputChange} />
<button onClick={clickButton}>提交</button>
</div>
<ul>
{
list.map((item,index)=>{
return (<li key={index}>{item}</li>)
})
}
</ul>
</div>
);
}
export default TodoListUI

4.引入react-redux进行应用数据管理

1)总入口中index.js中引入react-redux和容器组件APP
react-redux的核心:Provider(用于入口) 和 connect(用于数据和函数映射)
使用provider
/*
入口js
*/
import React from 'react';
import ReactDOM from 'react-dom'; import App from './containers/App';
import { Provider} from 'react-redux'
import store from './redux/store' //<Provider>是一个提供器,只要使用了这个组件,组件里边的其它所有组件都可以使用store了
//声明一个App容器组件,然后这个组件用Provider进行包裹。
const AppList = (
<Provider store={store}>
<App />
</Provider>
)
ReactDOM.render(AppList, document.getElementById('root'));
2)connect连接器(连接UI组件和redux中的action.js方法)成为容器组件
connect-连接器用来将redux管理的state数据映射成UI组件的一般属性(如输入框的值)
connect-连接器用来将redux管理的包含diaptch代码的函数映射成UI组件的函数属性的函数
1.在redux目录中的action.js定义UI组件要调用的方法,然后编写好reducer的业务逻辑
2.在containers容器APP组件中 引入UI组件TodolistUI和action进行连接

import React from 'react'
import {connect} from 'react-redux' import TodoListUI from '../components/TodoListUI'
import {inputChange,clickButton} from '../redux/actions' /*
connect-连接器用来将redux管理的state数据映射成UI组件的一般属性(如输入框的值)
指定向TodoList传入哪些一般属性(属性值的来源就是store中的state)
*/
const stateToProps = (state)=>{
return {
inputValue : state.inputValue,
list:state.list
}
} /*
connect-连接器用来将redux管理的包含diaptch代码的函数映射成UI组件的函数属性的函数
(如输入的onChange事件)
可以写多个函数,用逗号隔开
*/
// 写法1
// const dispatchToProps = (dispatch) =>{
// return {
// inputChange(e){
// //派发action到store中:定义action 然后派发
// //派发后就在reducer里边,编写对应的业务逻辑了
// let action = {
// type:'change_input',
// value:e.target.value
// }
// dispatch(action)
// },
// clickButton(){
//
// let action = {type:'add_item'}
// dispatch(action)
// }
// }
// }
//export default connect(stateToProps,dispatchToProps )(TodoListUI); // 写法2
export default connect(stateToProps,{inputChange,clickButton} )(TodoListUI);
5.引入 immutablejs
首先,我们有必要来划分一下边界,哪些数据需要使用不可变数据,哪些数据要使用原生js数据结构,哪些地方需要做互相转换
  • 在redux中,全局state必须是immutable的,这点毋庸置疑是我们使用immutable来优化redux的核心
  • 组件props是通过redux的connect从state中获得的,并且引入immutableJS的另一个目的是减少组件shouldComponentUpdate中不必要渲染,shouldComponentUpdate中比对的是props,如果props是原生JS就失去了优化的意义
  • 组件内部state如果需要提交到store的,必须是immutable,否则不强制
  • view提交到action中的数据必须是immutable
  • Action提交到reducer中的数据必须是immutable
  • reducer中最终处理state必须是以immutable的形式处理并返回
  • 与服务端ajax交互中返回的callback统一封装,第一时间转换成immutable数据

1)安装相关依赖

yarn add immutable  redux-immutable 

2)在reducer中 immutable的fromJs,把defalutState 转为immutable数据

 // 引入fromJS 将state数据转变为 immutable对象
const defalutState = fromJS({
inputValue : 'wuxiaohui',
list :[]
}); //immutablejs的相关接口——使用get 和set 方法来改变state
export default (state = defalutState,action) =>{
if(action.type === CHANGEINPUT){
// let newState = JSON.parse(JSON.stringify(state)) //深拷贝
// newState.inputValue = action.value
// return newState
return state.set('inputValue',action.value)
}
if(action.type === ADDITEMS){
// let newState = JSON.parse(JSON.stringify(state))
// newState.list.push(newState.inputValue)
// newState.inputValue = ''
// return newState return state.merge({
'list': state.get('list').push(state.get('inputValue')),
'inputValue': ''
}); } return state
}

3)在容器组件中App.js中映射时使用get获取相关属性值

 /*
connect-连接器用来将redux管理的state数据映射成UI组件的一般属性(如输入框的值)
指定向TodoList传入哪些一般属性(属性值的来源就是store中的state)
*/
const stateToProps = (state)=>{
return {
// inputValue : state.inputValue,
// list:state.list
//因为引入了immutable,state 已变为不可变对象只能调用get或set方法
inputValue : state.get('inputValue'),
list:state.get('list')
}
}
更多用法:
 

4)redux-immutable在reducer的处理

combineReducers(reducers)
随着应用变得越来越复杂,可以考虑将 reducer 函数 拆分成多个单独的函数,拆分后的每个函数负责独立管理 state 的一部分

类似这样

 import { combineReducers } from 'redux';
import { reducer as headerReducer } from '../common/header/store';
import { reducer as homeReducer } from '../pages/home/store';
import { reducer as detailReducer } from '../pages/detail/store';
import { reducer as loginReducer } from '../pages/login/store'; const reducer = combineReducers({
header: headerReducer,
home: homeReducer,
detail: detailReducer,
login: loginReducer
}); export default reducer;

假如我们的reducer在header中,组件中获取数据时,用get方法

const mapStateToProps = (state) => {
//inputValue是immutable对象,不能用state.header.inputValue的形式获取,要用get()
return {
inputValue :state.header.get('inputValue'),
list:state.header.get('list')
}
}

在使用了redux-immutable

 //combineReducers不再用rudux里的,而是redux-immutable里的,这样combineReducers里的对象就是一个immutable对象
//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;

获取数据的时候用get(),或者getIn()--获取结构化数据

 const mapStateToProps = (state) => {
return {
//inputValue :state.header.get('inputValue'),
// list:state.header.get('list')
inputValue :state.getIn(['header','inputValue']),
list:state.getIn(['header','list'])
}
}
 
流程中例子详见GitHub

react redux 二次开发流程的更多相关文章

  1. 实例讲解基于 React+Redux 的前端开发流程

    原文地址:https://segmentfault.com/a/1190000005356568 前言:在当下的前端界,react 和 redux 发展得如火如荼,react 在 github 的 s ...

  2. OMCS开发手册(04) -- 二次开发流程

    在掌握了前面几篇关于OMCS的详细介绍后,我们就可以正式基于OMCS进行二次开发了.下面我们就从服务端和客户端的角度分别介绍开发的步骤. 一.服务端开发 抛开具体的业务逻辑而言,就OMCS的服务端的开 ...

  3. C#开发BIMFACE系列2 二次开发流程

    系列目录     [已更新最新开发文章,点击查看详细] BIMFACE 平台是一个对外开放的平台,建筑行业的相关公司.软件公司或者有 BIM 业务需求的公司都可以注册成为开发者并使用其提供的强大功能. ...

  4. 【工业串口和网络软件通讯平台(SuperIO)教程】三.二次开发流程

    1.1    二次开发流程图 1.2    引用相关组件 找到“开发包”,引用里边的相关组件.如下图: 1.3    开发设备驱动模块 1.3.1    开发发送协议驱动 继承SuperIO.Devi ...

  5. Struts2学习笔记二:开发流程

    一:创建项目,添加依赖包 二:在web.xml配置核心控制器 <filter> <filter-name>struts2</filter-name> <fil ...

  6. 如何从零搭建一个webpack+react+redux+react-redux的开发环境一入门

    阅读本文章的时候,你要有一定的基础知识储备,简单的es6知识,模块化思想知识,js基础知识,node基础知识,react等 首先执行npm init,此时我的文件叫case; 下面安装一些需要的npm ...

  7. Ecshop系统二次开发教程及流程演示

      来源:互联网 作者:佚名 时间:03-01 16:05:31 [大 中 小] Ecshop想必大家不会觉得陌生吧,大部分的B2C独立网店系统都用的是Ecshop系统,很受用户的喜爱,但是由于Ecs ...

  8. PHPCMS V9 模块开发 二次开发实例 留言本

    鄙人实现了PHPCMS V9 产品开发权威指南(2011官方最新版).doc中的留言板实例,并加上模块安装和卸载功能, 程序可以运行,但只实现基本功能,目的是想让和我一样徘徊在PHPCMS门口不知道从 ...

  9. C#开发微信公众平台开发-微信海报介绍和开发流程

    “让客户发展客户”,微信海报才是微信公众平台最高明的吸粉手段,海报上有粉丝的专属二维码,有粉丝的头像及商户宣传的广告等.新粉丝扫描这个专属二维码会关注公众号,同时分享海报的粉丝会增加积分换取礼品或者优 ...

随机推荐

  1. 基于Docker搭建Jumpserver堡垒机操作实践

    一.背景 笔者最近想起此前公司使用过的堡垒机系统,觉得用的很方便,而现在的公司并没有搭建此类系统,想着以后说不定可以用上:而且最近也有点时间,因此来了搭建堡垒机系统的兴趣,在搭建过程中参考了比较多的文 ...

  2. docker运行原理与使用总结

    docker运行原理概述 Client-Server架构 docker守护进程运行在宿主机上systemctl start docker daemon进程通过socket从客户端(docker命令)接 ...

  3. SPOJ - Find The Determinant III 计算矩阵的行列式答案 + 辗转相除法思想

    SPOJ -Find The Determinant III 参考:https://blog.csdn.net/zhoufenqin/article/details/7779707 参考中还有几个关于 ...

  4. codeforces 830 B. Cards Sorting(线段树)

    题目链接:http://codeforces.com/contest/830/problem/B 题解:其实这题就是求当前大小的数到下一个大小的数直接有多少个数,这时候可以利用数据结构来查询它们之间有 ...

  5. CF991D Bishwock 第十七 贪心

    Bishwock time limit per test 1 second memory limit per test 256 megabytes input standard input outpu ...

  6. hdu5491 The Next 模拟

    Let LL denote the number of 1s in integer DD’s binary representation. Given two integers S1S1 and S2 ...

  7. Django+Nginx概念安装和使用–使用Django建立你的第一个网站

    一 前记 最近在使用Django倒腾属于自己的网站,由于以前没有接触过多少这类信息,所以,很多东西都是从零开始学习的.在参考网上的资料时候,发现很多对这方面记录的,很多人都写的不是很清楚,也许我这个新 ...

  8. Docker下使用disconf:细说demo开发

    Docker下的disconf实战全文链接 <Docker搭建disconf环境,三部曲之一:极速搭建disconf>: <Docker搭建disconf环境,三部曲之二:本地快速构 ...

  9. 第 15 篇:优化博客功能的细节,提升使用体验—— HelloDjango 系列教程

    作者:HelloGitHub-追梦人物 文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 在之前的系列教程中,我们已经实现了:文章的发布.展示.评论等功能,可能认真的小伙伴已经 ...

  10. 关闭同一网络内的windows主机

    声明这是技术讨论!切勿用来攻击别人,一切法律后果自负! 1. 在windows的cmd命令行下操作(如下操作都是以windows的机器在为主) net view #显示同一网络同所有主机 2. 打开远 ...