一、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. Active Directory participation features and security extensions

    Participation in the Active Directory Samba 3.0 series, as well as the OS since Windows 2000, is pos ...

  2. 7.Netty中 handler 的执行顺序

    1.Netty中handler的执行顺序 Handler在Netty中,无疑占据着非常重要的地位.Handler与Servlet中的filter很像,通过Handler可以完成通讯报文的解码编码.拦截 ...

  3. 天线basic

    1.实际应用时,按内置天线还是外置天线考虑. 内置时,净空区在 PCB 上所有层(all layer) 不能放置元件,走线和铺 GND  天线远离金属,至少要距离周围有较高的元器件 10 毫米以上: ...

  4. 取消任务(Task)

    private static void TaskCancelDemo() { //向应该被取消的 System.Threading.CancellationToken 发送信号 Cancellatio ...

  5. java8学习之BiFunction函数式接口实例演示&Predicate函数式接口详解

    BiFunction函数式接口: 在上次中已经对BiFunction接口进行了初步的认识,这里对它进一步学习,这里打算新建一个Person实体,然后新建若干个Person的实例存放在集合中,最后再根据 ...

  6. php正则表达式验证手机/固定电话/邮箱/身份证/银行卡自定义函数

    /** * 验证手机号码格式 * @param string $phone 手机号 * @return boolean */ function is_phone($phone) { $chars = ...

  7. 用脚本来运行scrapy crawl ...

    启动爬虫的命令为: scrapy crawl spidername(爬虫名) 方案(一)name.py #!/usr/bin/env python # -*- coding:utf-8 -*- fro ...

  8. Python之抓取网页元素

    import urllib.request from bs4 import BeautifulSoup url = "http://www.wal-martchina.com/walmart ...

  9. .NET面试题系列(二十一)C#中Equals和==的比较

    序言 值类型的比较 ; ; Console.WriteLine("Equals和= =(等于号)的比较"); Console.WriteLine("i.Equals(j) ...

  10. C语言 - sizeof和strlen的区别

    sizeof和strlen的区别: 1.sizeof操作符的结果类型是size_t,它在头文件中typedef为unsigned int类型. 该类型保证能容纳实现所建立的最大对象的字节大小. 2.s ...