React 之 Redux 的使用
Redux可以简单概况为:将需要修改的state都存入到store里,发起一个action用来描述发生了什么,用reducers描述action如何改变state tree 。创建store的时候需要传入reducer,真正能改变store中数据的是store.dispatch API。
1. Redux使用场景
- 某个组件的状态,需要共享
- 不同组件之间通信
2. Redux 特点

2.1 Store
store是一个数据仓库,一个应用中store是唯一的,它里面封装了state状态,当用户想访问state的时候,只能通过store.getState()来取得state对象。
2.2 action
action描述了一个更新state的动作,它是一个对象,其中type属性是必须有的,它指定了某动作和要修改的值:
{
type: CHANGE_INPUT_VALUE,
value: 'abc'
}
2.3 actionCreator
actionCreator 是一个方法,用来创建action对象,调用这个方法就能返回一个action对象,用于简化代码
2.4 dispatch
dispatch 是一个方法,它用于派发一个动作action,这是唯一的一个能够修改state的方法,它内部会调用reducer来调用不同的逻辑基于旧的state来更新出一个新的state。
2.5 reducer
reducer是更新state的核心,它里面封装了更新state的逻辑,reducer由外界提供(封装业务逻辑,在createStore时传入),并传入旧state对象和action,将新值更新到旧的state对象上返回。
3. Redux 三大原则
3.1 单一数据源
整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。组件通过如下方式取出state中数据:
console.log(store.getState())
3.2 State 是只读的
唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。
store.dispatch({
type: 'CHANGE_INPUT_VALUE',
value: 'abc'
})
3.3 使用纯函数来执行修改 reducers
为了描述 action 如何改变 state tree ,你需要编写 reducers。Reducer 只是一些纯函数,它接收先前的 state 和 action,并返回新的 state。
const defaultState = { // 默认一个state
inputValue: 'abc',
list: [1,2,3]
};
export default (state = defaultState, action) => {
console.log(state, action);
if (action.type === 'CHANGE_INPUT_VALUE') {
let newState = JSON.parse(JSON.stringify(state)); // 深拷贝一份state
newState.inputValue = action.value; // 更改拷贝后的state
return newState; // 将更新后的新的state 返回给 store
}
return state;
}
4 示例应用 - Todolist

入口文件 /src/index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Todolist from './Todolist';
ReactDOM.render(<Todolist />, document.getElementById('root'));
新建文件 src/Todolist.js
import React, { Component, Fragment } from 'react';
class TodoList extends Component {
render() {
return (
<Fragment>
<div style={{padding: '10px'}}>
todolist
</div>
</Fragment>
)
}
}
export default TodoList;
4.1 创建 store
新建目录: /src/store
4.2 store 入口文件
创建文件:/src/store/index.js:
import { createStore } from 'redux'
import reducer from './reducer'
const store = createStore(reducer)
export default store
4.3 统一定义action.type
新建文件:/src/store/actionType.js,
export const CHANGE_INPUT_VALUE = 'change_input_value'; // 更改input处输入框里面的值
export const ADD_TOTO_ITEM = 'add_todo_item'; // 添加待办事项
export const DELETE_TODO_ITEM = 'detete_todo_item'; // 删除待办事项
4.4 创建action对象
新建文件:/src/store/actionCreator.js
// 引入 actionType 模块
import {
CHANGE_INPUT_VALUE,
ADD_TOTO_ITEM,
DELETE_TODO_ITEM,
} from './actionType'
// 更改input处输入框里面的值
export const getInputChangeAction = (value) => {
return {
type: CHANGE_INPUT_VALUE,
value
}
}
// 添加待办事项
export const getAddItemAction = () => {
return {
type: ADD_TOTO_ITEM
}
}
// 删除待办事项
export const getDeleteItemAction = (index) => {
return {
type: DELETE_TODO_ITEM,
index
}
}
4.5 reducer 更新 state
新建文件:/src/store/reducer.js
import {
CHANGE_INPUT_VALUE,
ADD_TOTO_ITEM,
DELETE_TODO_ITEM,
} from './actionType'
const defaultState = { // 默认一个state
inputValue: 'abc',
list: [1,2,3]
};
// 注意:reducer 可以接收state, 但是不允许修改state,所以需要深拷贝一份state
export default (state = defaultState, action) => {
console.log(state, action);
if (action.type === CHANGE_INPUT_VALUE) {
let newState = JSON.parse(JSON.stringify(state)); // 深拷贝一份state
newState.inputValue = action.value; // 更改拷贝后的state
return newState; // 将更新后的新的state 返回给 store
}
if (action.type === ADD_TOTO_ITEM) {
let newState = JSON.parse(JSON.stringify(state));
newState.list.push(newState.inputValue);
newState.inputValue = '';
return newState;
}
if (action.type === DELETE_TODO_ITEM) {
let newState = JSON.parse(JSON.stringify(state));
newState.list.splice(action.index, 1); // 删除当前index的item
return newState;
}
return state;
}
4.6 修改 src/Todolist.js
import React, { Component, Fragment } 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';
class TodoList extends Component {
constructor(props) {
super(props);
this.state = store.getState();
this.handleInputChange = this.handleInputChange.bind(this);
this.handleBtnClick = this.handleBtnClick.bind(this);
this.handleStoreChange = this.handleStoreChange.bind(this);
// 订阅store,只要store中state有变化,就执行handleStoreState函数
store.subscribe(this.handleStoreChange);
}
handleInputChange (e) {
const action = getInputChangeAction(e.target.value);
// 将需要执行的action传给store
store.dispatch(action);
}
handleBtnClick () {
const action = getAddItemAction();
store.dispatch(action);
}
handleItemDelete (index) {
const action = getDeleteItemAction(index);
store.dispatch(action);
}
handleStoreChange () {
// 当store中state变化时,则重新取一次数据进行替换
this.setState(store.getState());
}
render() {
return (
<Fragment>
<div style={{padding: '10px'}}>
<div>
<Input
value={this.state.inputValue}
placeholder="input something"
style={{width: '300px',marginRight: '10px'}}
onChange={this.handleInputChange}
/>
<Button type="primary" onClick={this.handleBtnClick}>提交</Button>
</div>
<List
style={{marginTop: '10px', width: '300px'}}
bordered
dataSource={this.state.list}
renderItem={
(item, index) => <List.Item onClick={this.handleItemDelete.bind(this, index)}>{item}</List.Item>
}
/>
</div>
</Fragment>
)
}
}
export default TodoList;
5 项目目录

React 之 Redux 的使用的更多相关文章
- 实例讲解react+react-router+redux
前言 总括: 本文采用react+redux+react-router+less+es6+webpack,以实现一个简易备忘录(todolist)为例尽可能全面的讲述使用react全家桶实现一个完整应 ...
- 基于 React.js + Redux + Bootstrap 的 Ruby China 示例 (转)
一直学 REACT + METEOR 但路由部分有点问题,参考一下:基于 React.js + Redux + Bootstrap 的 Ruby China 示例 http://react-china ...
- 基于react+react-router+redux+socket.io+koa开发一个聊天室
最近练手开发了一个项目,是一个聊天室应用.项目虽不大,但是使用到了react, react-router, redux, socket.io,后端开发使用了koa,算是一个比较综合性的案例,很多概念和 ...
- 最新的chart 聊天功能( webpack2 + react + router + redux + scss + nodejs + express + mysql + es6/7)
请表明转载链接: 我是一个喜欢捣腾的人,没事总喜欢学点新东西,可能现在用不到,但是不保证下一刻用不到. 我一直从事的是依赖angular.js 的web开发,但是我怎么能一直用它呢?看看最近火的一塌糊 ...
- 【前端】react and redux教程学习实践,浅显易懂的实践学习方法。
前言 前几天,我在博文[前端]一步一步使用webpack+react+scss脚手架重构项目 中搭建了一个react开发环境.然而在实际的开发过程中,或者是在对源码的理解中,感受到react中用的最多 ...
- 【前端,干货】react and redux教程学习实践(二)。
前言 这篇博文接 [前端]react and redux教程学习实践,浅显易懂的实践学习方法. ,上一篇简略的做了一个redux的初级demo,今天深入的学习了一些新的.有用的,可以在生产项目中使用的 ...
- [React] 14 - Redux: Redux Saga
Ref: Build Real App with React #14: Redux Saga Ref: 聊一聊 redux 异步流之 redux-saga [入门] Ref: 从redux-thun ...
- [React] 15 - Redux: practice IM
本篇属于私人笔记. client 引导部分 一.assets: 音频,图片,字体 ├── assets │ ├── audios │ ├── fonts │ └── images 二.main&quo ...
- react脚手架改造(react/react-router/redux/eslint/karam/immutable/es6/webpack/Redux DevTools)
公司突然组织需要重新搭建一个基于node的论坛系统,前端采用react,上网找了一些脚手架,或多或少不能满足自己的需求,最终在基于YeoMan的react脚手架generator-react-webp ...
- React 与 Redux 在生产环境中的实践总结
React 与 Redux 在生产环境中的实践总结 前段时间使用 React 与 Redux 重构了我们360netlab 的 开放数据平台.现将其中一些技术实践经验总结如下: Universal 渲 ...
随机推荐
- python3中“->”的含义
->:标记返回函数注释,信息作为.__annotations__属性提供 __annotations__属性是字典.键return是用于在箭头后检索值的键.但是在Python中3.5,PEP 4 ...
- Layui 关闭当前标签页
parent.layui.admin.events.closeThisTabs();
- 洛谷p2827蚯蚓题解
题目 算法标签里的算法什么的都不会啊 什么二叉堆?? qbxt出去学习的时候讲的,一段时间之前做的,现在才写到博客上的 维护3个队列,队列1表示最开始的蚯蚓,队列2表示每一次被切的蚯蚓被分开的较长的那 ...
- flex布局整理以及demo
flex: 概念: flex容器: display:flex flex项: 轴:水平的主轴.垂直的交叉轴 容器的属性: 1. flex-direction(决定主轴的方向.即项目的排列方向) 1.1 ...
- 学好Python后可从事岗位+学习Python的难度
一.学好Python好就业: 1.Linux运维.Linux运维是必须而且一定要掌握Python语言,Python可以满足Linux运维工程师的工作需求提升效率,总而提升自己的能力.用Python实现 ...
- js 测试题
//身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字母x function isCardNo(card) { }$)|(^\d{}(\d|X|x) ...
- linux脚本中有source相关命令时的注意事项
写这个问题起因是因为一个同学去的java一键脚本环境变量设置问题, [root@localhost u01]# more 1.sh #!/bin/bash grep -q "export J ...
- python3.5-ssh免输入密码过程
ssh远程批量执行命令要输密码很蛋疼,虽然有很多种方式,大概有4.5种.原理基本类似. 这里我就讲一个python的模拟登陆 模块 此刻的时间是:2015年11月19日11:11:47 ...
- python 散点图上给每个点打标签方便看到数据
import numpy as np import matplotlib.pyplot as plt x=[2.3,4.5,3,7,6.5,4,5.3] y=[5,4,7,5,5.3,5.5,6.2] ...
- backend介绍
开发环境: windows python django 2.2 一个django 后台管理的app 将后台管理组件化, 不依赖于项目, 只要简单配置就可以使用, 开发业务逻辑也非常方便 其主要包含三个 ...