React从入门到放弃之前奏(3):Redux简介
安装
npm i -S redux react-redux redux-devtools
概念
在redux中分为3个对象:Action、Reducer、Store
Action
- 对行为(如用户行为)的抽象
- Action 就是一个普通 JavaScript 对象。如:
{ type: 'ADD_TODO', text: 'Go to swimming pool' }(其中type字段是约定也是必须的) - 作为Reducer的参数
Reducer
- 一个普通的函数,用来修改store的状态。
- 函数签名:
(currentState,action)=>newState- 在 default 情况下返回currentState
Object.assign({},state, { visibilityFilter: action.filter })(第一个参数不能为state) 等价于ES7的{ ...state, ...newState }
- redux 的 combineReducers 方法可合并reducer
Store
- 代表数据模型,内部维护了一个state变量
- 两个核心方法,分别是getState、dispatch。前者用来获取store的状态(state),后者用来修改store的状态
- createStore(reducer) 可创建Store
redux示例:
import { createStore } from 'redux'
// reducer
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1
default:
return state
}
}
// state
let store = createStore(counter); // 会调用
// 监听
store.subscribe(() =>
console.log(store.getState())
);
// 调用reducer
store.dispatch({ type: 'INCREMENT' });
react-redux
react的需求:
- 数据总是单向从顶层向下分发的
- 组件之间的沟通通过提升state:子组件改变父组件state的办法只能是通过onClick触发父组件声明好的回调
- state越来越复杂:单页应用的发展导致。包括服务器响应、缓存数据、本地生成尚未持久化到服务器的数据,也包括 UI 状态,如激活的路由,被选中的标签,是否显示加载动效或者分页器等等。
react-redux 将react组件分为2种:展示组件 和 容器组件
展示组件
描述如何展示:负责UI样式的展示
- 数据来源:props
- 数据修改:通过props的回调函数
- 不直接使用redux
容器组件
描述如何运行:负责数据获取 和 状态更新
- 数据来源:redux state
- 数据修改:redux 派发action
- 直接使用redux
react-redux 只有2个API:Provider 和 connect
Provider
<Provider store>
- 在原应用组件上包裹一层,使原来整个应用成为Provider的子组件
- 接收Redux的store作为props,内部通过context对象传递给子孙组件上的connect
connect
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])(Component)
作用:连接React组件与 Redux store
mapStateToProps(state, ownProps) : stateProps:
- 将 store 中的数据作为 props 绑定到组件上。
- 当 state 变化,或者 ownProps 变化的时候,mapStateToProps 都会被调用,计算出一个新的 stateProps
mapDispatchToProps(dispatch, ownProps): dispatchProps:将 dispatch(action) 作为 props 绑定到组件上
mergeProps:指定 stateProps 以及 dispatchProps 合并到 ownProps 的方式。(默认使用Object.assign)
connect是个高阶组件(HOC)大致源码:
export default function connect(mapStateToProps, mapDispatchToProps, mergeProps, options = {}) {
return function wrapWithConnect(WrappedComponent) {
class Connect extends Component {
constructor(props, context) {
this.store = props.store || context.store
this.stateProps = computeStateProps(this.store, props)
this.dispatchProps = computeDispatchProps(this.store, props)
this.state = { storeState: null }
// 合并stateProps、dispatchProps、parentProps
this.updateState()
}
shouldComponentUpdate(nextProps, nextState) {
// 进行判断,当数据发生改变时,Component重新渲染
if (propsChanged || mapStateProducedChange || dispatchPropsChanged) {
this.updateState(nextProps)
return true
}
}
componentDidMount() {
this.store.subscribe( () => this.setState({ storeState: this.store.getState() }) )
}
render() {
return (
<WrappedComponent {...this.nextState} />
)
}
}
return Connect;
}
}
react-redux示例:
Counter.js
import React, { Component } from 'react';
import { createStore, bindActionCreators } from 'redux';
import { Provider, connect } from 'react-redux';
function clickReduce(state = { todo: 1 }, action) {
switch (action.type) {
case 'click':
return Object.assign({}, state, { todo: state.todo + 1 });
default:
return state;
}
}
let store = createStore(clickReduce);
class Counter extends Component {
render() {
return (
<div>
<div>{this.props.todo}</div>
<button onClick={this.props.clickTodo}>Click</button>
</div>
)
}
}
// 方式1:
export default connect(state => ({ todo: state.todo }),
dispatch => ({ clickTodo: () => dispatch({ type: 'click' }) }))(Counter)
// 方式2:
export default connect(state => ({ todo: state.todo }),
dispatch => bindActionCreators({ clickTodo: () => ({ type: 'click' }) }, dispatch))(Counter);
index.js
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { render } from 'react-dom';
import Clock from './Clock'
render((
<Provider store={store}>
<Counter />
</Provider>), root);
在redux中,我们只能dispatch简单的action对象。
对应的在react-redux中,我们只能定义同步的reducer方法。
下节将介绍在react-redux如何定义异步方法。让其更加适用于生产环境。
React从入门到放弃之前奏(3):Redux简介的更多相关文章
- React从入门到放弃之前奏(5):ReactRouter4
概念 安装:npm i -S react-router react-router-dom GitHub:ReactTraining/react-router React Router中有三种类型的组件 ...
- React从入门到放弃之前奏(1):webpack4简介
接触webpack是好久之前的事情了,最近看了下webpack没想到都到4了. webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler). 会创建1个 ...
- React从入门到放弃之前奏(2):React简介
本系列将尽可能使用ES6(ES2015)语法.所以均在上节webpack的基础上做开发. React是Facebook开发的一款JS库,因为基于Virtual DOM,所以响应速度快,以及支持跨平台. ...
- React从入门到放弃之前奏(4):Redux中间件
redux 提供了类似后端 Express 的中间件概念. 最适合扩展的是redux中的 store.dispatch 方法,中间件实际就是通过 override redux的store.dispat ...
- 在 2016 年学 JavaScript 是一种什么样的体验?(React从入门到放弃)
jquery 年代 vs 前端模块化 http://blog.csdn.net/offbye/article/details/52793921 ++ 嘿,我最近接到一个 Web 项目,不过老实说,我这 ...
- ubuntu-docker入门到放弃(七)Dockerfile简介
一.dockerfile基本结构 最简单的理解就是dockerfile实际上是一些命令的堆叠,有点像最基础的shell脚本,没有if 没有for,就是串行的一堆命令. 一般而言,dockerfile分 ...
- D3.js从入门到“放弃”指南
前言 近期略有点诸事不顺,趁略有闲余之时,玩起D3.js.之前实际项目中主要是用各种chart如hightchart.echarts等,这些图形库玩起来貌都是完美的,一切皆可配置,但几年前接触了D3之 ...
- 一天带你入门到放弃vue.js(一)
写在前面的话! 每个新的框架入手都会进行一些列的扯犊子!这里不多说那么多!简简单单说一下vue吧! Vue.js是目前三大框架(angular,vue,react)之一,是渐进式js框架,据说是摒弃了 ...
- 小白学 Python 爬虫(28):自动化测试框架 Selenium 从入门到放弃(下)
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
随机推荐
- 如何利用c中的指针实现两个8bit的数合并为16bit
对于从事单片机开发,进行单片机c语言开发的人来说,在对外部信息采集回来的数据进行处理,经常会用到,将采集到的第一个字节作为高8位,采集到的第二个字节作为低8位,从而构成1个16bit的数,得到一次完整 ...
- python select.select模块通信全过程详解
要理解select.select模块其实主要就是要理解它的参数, 以及其三个返回值.select()方法接收并监控3个通信列表, 第一个是所有的输入的data,就是指外部发过来的数据,第2个是监控和接 ...
- 关于iOS9 HTTP不能正常使用的解决方法
在工程的info.plist文件中添加NSAPPTransportSecurity类型为Dictionary,在NSAPPTransportSecurity下添加NSAllowsArbitraryLo ...
- Swift内部类调用外部类方法、属性的变通
Swift的内部类比较鸡肋,在内部类里面不能调用外部类的属性或方法,那么如何解决这个问题,把内部类里面调用外部类的那部分代码方法移动到外部类里面,成为外部类的方法,是一种变通解决方式.
- RDC去省赛玩前の日常训练 Chapter 2
2018.4.9 施展FFT ing! 马上就要和前几天学的斯特林数双剑合璧了!
- Python Tips阅读摘要
发现了一本关于Python精通知识点的好书<Python Tips>,关于Python的进阶的技巧.摘录一些比较有价值的内容作为分享. *args and **kwargs 在函数定义的时 ...
- Node笔记四
异步操作 -Node采用chrome v8 引擎处理javascript脚本 --v8最大特点就是单线程运行,一次只能运行一个任务 -Node大量采用异步操作 --任务不是马上执行,而是插在任务队列的 ...
- Python入门、练手、视频资源汇总,拿走别客气!
摘要:为方便朋友,重新整理汇总,内容包括长期必备.入门教程.练手项目.学习视频. 一.长期必备. 1. StackOverflow,是疑难解答.bug排除必备网站,任何编程问题请第一时间到此网站查找. ...
- 用 Python 鉴别色色的图片
0 前言 实话实说啊,这个标题起得就有点标题党,识别是识别,准确率就有点玄学了. 1 环境说明 Win10 系统下 Python3,编译器是 Pycharm,需要安装 nonude 这个库. Pych ...
- Maven安装和使用
一.安 装 1.解压好后,添加系统环境变量 变量名:MAVEN_HOME 属性值:D:\apache-maven-3.3.3 //也就是解压的路径 path中添加:%MAVEN_HOME%\bi ...