一、React项目中为什么要用Redux

  上图:

左图当使用纯React开发稍微大点的项目,因为React数据是瀑布式的,只能通过父子组件传递数据,所以实现关系不大的两React的组件之间的数据传递就会让你非常难受,操作起来非常复杂。如右图,由此应运而生了Redux数据流框架,专门解决数据流问题,

Redux的基本原理就是React的所有组件涉及到的数据全部都存储在共用的Store中,这样所有组件都可以通过Store来改动数据和获取数据,非常方便。

二、Redux安装

在已经安装yarn的前提下

yarn add redux

  

三、Redux工作流讲解

先上图:

为了方便理解,我将一个redux的操作流程视为从图书馆取书的流程:

1、React Components(借书人)

2、说借一本《React全栈》书(Action Creations就是代表需要进行的操作)

3、Store(图书馆管理员)听到了这句话

4、从reducers(记书本)中查询书在哪放着

5、Store(图书馆管理员)查到(即reducers返回newState)

6、Store(图书馆管理员)将书交给React Components(借书人)(即:将改动后的state发给React Components(借书人))

四、Redux使用入门

1、使用谷歌浏览器下载浏览器rudux插件(建议开启科学上网后下载安装)

2、在src目录下创建store文件夹

3、在store文件夹下创建index.js文件作为redux的入口文件

import {createStore} from 'redux';
// 引入reducer
import reducer from './reducer'; const store = createStore(
reducer,
// 显示redux调试工具
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
); export default store;

  

4、在store文件夹下创建reducer.js文件作为数据

import {CHANGE_INPUT_VALUE , ADD_TODO_ITEM , DELETE_TODO_ITEM} from './actionTypes';

const defaultState = {
inputValue : "",
list: []
}; //reducers可以接收state但是绝不能修改state
//reducers不能有异步操作也不能有与时间相关的操作,也不能对接收的参数进行修改
//返回纯函数,纯函数指的是:给定固定输入,则输出固定,而且不会有任何副作用
export default (state = defaultState,action) => {
// state是上一个store中存储的数据,action是用户发过来的操作请求
// 1、JSON.parse()用于从一个字符串中解析出json对象
// 2、JSON.stringify()用于从一个对象解析出字符串
if (action.type === CHANGE_INPUT_VALUE) {
// state深拷贝
const newState = JSON.parse(JSON.stringify(state));
newState.inputValue = action.value;
return newState;
}
if (action.type === ADD_TODO_ITEM) {
// state深拷贝
const newState = JSON.parse(JSON.stringify(state));
newState.list.push(newState.inputValue);
newState.inputValue = '';
return newState;
}
if (action.type === DELETE_TODO_ITEM) {
// state深拷贝
const newState = JSON.parse(JSON.stringify(state));
newState.list.splice(action.index, 1);
return newState;
}
return state;
}

  

5、核心组件中导入store

import React,{Component} from 'react';
import 'antd/dist/antd.css';
import {Input, Button, List} from 'antd';
import store from './store/index';
import {getInputChangeAction, getAddItemAction, getDeleteItemAction} from './store/actionCreators'
// import {CHANGE_INPUT_VALUE , ADD_TODO_ITEM , DELETE_TODO_ITEM} from './store/actionTypes'; class TodoList extends Component{ constructor(props){
super(props);
this.state = store.getState();
this.handleInputChange = this.handleInputChange.bind(this);
this.handleStoreChange = this.handleStoreChange.bind(this);
this.handleBtnClick = this.handleBtnClick.bind(this);
// 监听store中数据的变化,改变则通过handleStoreChange()函数重新渲染
store.subscribe(this.handleStoreChange)
} render(){
return(
<div style={{margin:'30px'}}>
<div>
<Input
type="text"
value={this.state.inputValue}
placeholder='todo info'
style={{width:'300px',marginRight:'10px'}}
onChange={this.handleInputChange}
/>
<Button type="primary" onClick={this.handleBtnClick}>提交</Button>
</div>
<div>
<List
style={{width:'300px',marginTop:'10px'}}
bordered
// 数据源
dataSource={this.state.list}
renderItem={(item,index) => (<List.Item onClick={this.handleItemDelete.bind(this,index)}>{item}</List.Item>)}
/>
</div>
</div>
)
} // 输入框改变
handleInputChange(e){
const action = getInputChangeAction(e.target.value);
// 将action派发给store
store.dispatch(action);
} // 数据重新获取并渲染
handleStoreChange(){
// store.getState()从store中重新取数据
// this.setState()更新数据
this.setState(store.getState())
} // 点击后增添数据
handleBtnClick(){
// 创建action对象
const action = getAddItemAction();
// 将action发给store
store.dispatch(action);
} handleItemDelete(index){
const action = getDeleteItemAction(index);
store.dispatch(action);
} } export default TodoList;

  

6、升级——store中创建actionCreators

import {ADD_TODO_ITEM, CHANGE_INPUT_VALUE, DELETE_TODO_ITEM} from "./actionTypes";

export const getInputChangeAction = (value) => ({
type : CHANGE_INPUT_VALUE,
value
}); export const getAddItemAction = () => ({
type : ADD_TODO_ITEM
}); export const getDeleteItemAction = (index) => ({
type : DELETE_TODO_ITEM,
index
});

  

7、升级——store中创建actionTypes

export const CHANGE_INPUT_VALUE = 'change_input_value';
export const ADD_TODO_ITEM = 'add_todo_item';
export const DELETE_TODO_ITEM = 'delete_todo_item';

  

【React自制全家桶】九、Redux入手的更多相关文章

  1. 【React自制全家桶】六、React性能优化(持续更新总结)

    一.通过虚拟DOM来提升性能(自动) 底层讲解见[React自制全家桶]二.分析React的虚拟DOM和Diff算法   二.将多次setState合并为一次执行(自动) 底层讲解见[React自制全 ...

  2. 【React自制全家桶】四、React中state与props的分析与比较

    一.state 1.state的作用 state是React中组件的一个对象.React把用户界面当做是状态机,想象它有不同的状态然后渲染这些状态,可以轻松让用户界面与数据保持一致. React中,更 ...

  3. 【React自制全家桶】一、Webstrom+React+Ant Design+echarts搭建react项目

    前言 一.React是Facebook推出的一个前端框架,之前被用于著名的社交媒体Instagram中,后来由于取得了不错的反响,于是Facebook决定将其开源.出身名门的React也不负众望,成功 ...

  4. 【React自制全家桶】八、React动画以及react-transition-group动画库的使用

    React动画通常有三种方法实现从易到难为: 1.transition(CSS3自带) 2.animation(CSS3自带) 3.react-transition-group动画库(需要引入插件) ...

  5. 【React自制全家桶】七、React实现ajax请求以及本地数据mock

    一.下载axios插件 yarn add axios 二.React的ajax请求代码如何放置 建议放置在生命周期函数之componentDidMount()中 三.ajax之get请求 axios. ...

  6. 【React自制全家桶】五、React组件的生命周期函数详解

    一.总览React组件的生命周期函数 什么是生命周期函数:简单的来说就是 在某个时刻会自动执行的函数 二.React的生命周期函数主要由四块组成 分别是:组件初始化.组件挂载.组件更新.组件卸载 三. ...

  7. 【React自制全家桶】三、React使用ref操作DOM与setState遇到的问题

    在React中同时使用ref操作DOM与setState常常会遇到 比如操作的DOM是setState更新之前的DOM内容,与想要的操作不一致.导致这样的原因是setState函数是异步函数. 就是当 ...

  8. 【React自制全家桶】二、分析React的虚拟DOM和Diff算法

    一.React如何更新DOM内容: 1.  获取state 数据 2.  获取JSX模版 3.  通过数据 +模版结合,生成真实的DOM, 来显示,以下行代码为例(简称代码1) <div id= ...

  9. react 项目全家桶构件流程

    资源:create-react-app.react.react-dom.redux.react-redux.redux-thunk.react-router-dom.antd-mobile/antd. ...

随机推荐

  1. Delphi DLL文件的静态调用

  2. 第十三章·Kibana深入-使用地图统计客户端IP

    地址库 在ELK中,我们可以使用地址库,来对IP进行分析,对日志进行分析,在ELKstack中只有Logstash可以做到,但是出图,是Kibana来出的,所以我们首先需要下载地址库数据文件,然后对L ...

  3. Centos网卡名称命名

    1. vim /etc/sysconfig/grub     编辑/etc/sysconfig/grub文件 添加  net.ifnames=0 biosname=0 GRUB_TIMEOUT= GR ...

  4. Vi 入门简易教程

    首先,请注意,以下所讲的,全部是键盘在英文输入模式下.如果键盘是在中文输 入模式,全部的指令不正确. vi 有两种模式: Command Mode(指令模式) and Insert Mode(我姑且称 ...

  5. android 拍照上传文件 原生定位

    最近公司需要一个android拍照上传和定位功能的的单一功能页面,一开始选择ionic cordova angular的一套H5框架,但是遇到和上传文件报错的问题,bug找了一天没找到原因,怀疑是io ...

  6. .net core 读取appsettings 的配置

    { "Logging": { "IncludeScopes": false, "LogLevel": { "Default&quo ...

  7. css 判断是iphone4s iphone5 加载不同样式

    @media (device-height:480px) and (-webkit-min-device-pixel-ratio:2){/* 兼容iphone4/4s */ .class{}}@med ...

  8. 基于node.js的websocket 前后端交互小功能

    一.node var ws = require("nodejs-websocket"); console.log("开始建立连接...") var server ...

  9. PHP:函数和语言结构(转)

    转自:https://www.cnblogs.com/fanqiechaodan/articles/5222366.html 什么是语言结构呢?它和函数有什么不同吗? 1.  什么是语言结构和函数 语 ...

  10. java常用数据类型转换

    在Java开发过程中经常会涉及到数据类型的转换问题,比如数字型转字符型,字符型转日期型,字符串转数组等等,以及其他类型的强制转换等.经常出现,所以有必要总结一下. 1.如何将字串 String 转换成 ...