第一节 深度学习Redux成员及其数据流
1、actions
. actions其实是描述 操作的对象,我们调用dispatch时需要传入此对象
2、store
. store是整个应用的数据存储仓库,负责我们全局管理端的状态数据存储
3、reducers
. reducers接收action并更新store
4、注意:redux是一个单独的数据流框架,跟react没有直接的关系,我们也可以在JQ在其他的复杂项目里面使用redux进行数据管理,当我们不知道是否应该使用redux的时候,我们都是不需要的。因为只有我们很肯定redux能帮助我们管理好复杂项目数据流的时候它才能发挥它的威力,简单的项目我们使用state+props+context 或者 Hooks足够。
5、Redux数据流走向
6、其他数据状态管理对比学习
flux:
dva:
mobx:
vuex:
第二节 学习redux编写一个累加器程序
1、安装redux npm install rudex --save
2、编写使用redux的步骤(过程有点繁琐,别遗漏任何一个步骤)
2.1. 从redux 引入 createStore用来创建数据仓库store
createStore是一个函数,需要传入reducer作为参数,返回值是我们需要的store
2.2. 在使用页面引入数据仓库store
通过getState()方法可以获取到数据仓库里的状态数据state
通过dispatch(action)可以出发更改reducer函数
每次触发dispatch都会触发store.subscribe()方法,用来重新触发页面渲染
2.3代码展示,对应以上步骤
store.js
import { createStore } from 'redux';
// 编写我们的第一个reducer
const firstReducer = (state = 10, action) => {
switch (action.type) {
case 'add':
return state + 1;
case 'reduce':
return state - 1;
default:
return state;
}
}
// 创建数据仓库
const store = createStore(firstReducer);
export default store
FirstRedux.js
import React, { Component } from 'react';
import store from './store';
export default class FirstRedux extends Component {
render() {
return (
<div>
<h5>第2节、纯redux累加器</h5>
{/* 通过我们的store 的 getState 可以获取到我们 state 数据 */}
<p>{store.getState()}</p>
<div>
{/* 通过我们的store 的 dispatch 可以改变数据 */}
<button onClick={()=>store.dispatch({type:'add'})}>加1</button>
<button onClick={()=>store.dispatch({type:'reduce'})}>减1</button>
</div>
</div>
)
}
}
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import ReduxDemo from './ReduxDemo';
import store from './redux-demo/store';
const render = ()=>{
ReactDOM.render(<ReduxDemo></ReduxDemo>,document.getElementById('root'));
}
render();
store.subscribe(render);
第三节 react-redux使用
1、由于redux的写法太繁琐,还每次需要重新render,不太符合react
2、安装react-redux:npm install react-redux --save
3、React-redux 提供了2个 api 供我们使用
3.1 Provider 顶级组件,为我们(注入)提供数据功能
3.2 connect 高阶组件,为我们提供数据和方法(就是一个函数,传入一个组件,返回另一个新的组件)
4、如下是用react-redux 改造的累加器代码,只需要index.js 和 FirstRedux.js,store.js不变
5、改造中出现报错:检查react-dom、react、react-redux、redux版本后,重新安装一下,兼容问题消失
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import ReduxDemo from './ReduxDemo';
import store from './redux-demo/store';
import { Provider } from 'react-redux';
ReactDOM.render(
<Provider store={store}>
<ReduxDemo></ReduxDemo>
</Provider>, document.getElementById('root')
);
FirstRedux.js
import React, { Component } from 'react';
import {connect} from 'react-redux';
// 返回数据方法,供我们的connect使用,他会将数据转换成props
const mapStateToProps = (state)=>{
return {
count:state
}
}
// 返回dispatch方法的方法,供我们的connect使用,他会将dispatch转换成props
const mapDispatchToProps = (dispatch)=>{
return {
add:()=>dispatch({type:'add'}),
reduce:()=>dispatch({type:'reduce'}),
}
}
class FirstRedux extends Component {
render() {
return (
<div>
<h5>第3节、react-redux累加器</h5>
<p>{this.props.count}</p>
<div>
<button onClick={()=>this.props.add()}>加1</button>
<button onClick={()=>this.props.reduce()}>减1</button>
</div>
</div>
)
}
}
export default connect(mapStateToProps,mapDispatchToProps)(FirstRedux);
第四节 高阶组件装饰器模式简化封装代码
1、connect高阶组件使用装饰器会使我们的代码看起来更简洁易懂
2、代码如下:
FirstRedux.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
@connect(
state => ({ count: state }),
// dispatch=>({
// add:()=>dispatch({type:'add'}),
// reduce:()=>dispatch({type:'reduce'})
// })
// 简写dispatch (因为dispath只支持同步写法)
{
add: () => ({ type: 'add' }),
reduce: () => ({ type: 'reduce' })
}
)
class FirstRedux extends Component {
render() {
return (
<div>
<h5>第3节、react-redux累加器</h5>
<p>{this.props.count}</p>
<div>
<button onClick={() => this.props.add()}>加1</button>
<button onClick={() => this.props.reduce()}>减1</button>
</div>
</div>
)
}
}
export default FirstRedux;
第五节 redux中间件:异步+日志
1、用于redux reducer默认只支持同步,实现异步任务或者延时任务时,我们就要借助中间件的支持了
2、学习两个中间件
2.1 redux-thunk 支持我们reducer在异步操作结束后自动执行
2.2 redux-logger 打印日志协助本地调试
2.3 安装:npm install redux-thunk redux-logger --save
2.4 注意点:applyMiddleware(thunk,logger) 中间件的使用是有先后顺序的(先传入先试用),日志最好放在最后
3、使用例子 ****redux-logger
store.js
import { createStore, applyMiddleware } from 'redux';
import logger from 'redux-logger'
// 编写我们的第一个reducer
const firstReducer = (state = 10, action) => {
switch (action.type) {
case 'add':
return state + 1;
case 'reduce':
return state - 1;
default:
return state;
}
}
// 创建数据仓库
const store = createStore(firstReducer,applyMiddleware(logger));
export default store
页面效果
4、使用例子 ****redux-thunk
FirstRedux.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
@connect(
state => ({ count: state }),
{
add: () => ({ type: 'add' }),
reduce: () => ({ type: 'reduce' }),
asyncAdd:() => dispatch=>{
setTimeout(()=>{
dispatch({type: 'add'})
},2000)
}
}
)
class FirstRedux extends Component {
render() {
return (
<div>
<p>{this.props.count}</p>
<div>
<button onClick={() => this.props.add()}>加1</button>
<button onClick={() => this.props.reduce()}>减1</button>
<button onClick={() => this.props.asyncAdd()}>延时加1</button>
</div>
</div>
)
}
}
export default FirstRedux;
注意点:不使用中间件异步报错
store.js 使用中间件,进行异步的reducer,更新store数据。
import { createStore, applyMiddleware } from 'redux';
import logger from 'redux-logger';
import thunk from 'redux-thunk';
// 编写我们的第一个reducer
const firstReducer = (state = 10, action) => {
switch (action.type) {
case 'add':
return state + 1;
case 'reduce':
return state - 1;
default:
return state;
}
}
// 创建数据仓库
const store = createStore(firstReducer,applyMiddleware(thunk,logger));
export default store
第六节 抽离reducer和action统一管理
1、不在组件内定义reducer的action,集中管理
sotre.js 数据仓库 action定义。
// 编写我们的第一个reducer
const firstReducer = (state = 10, action) => {
switch (action.type) {
case 'add':
return state + 1;
case 'reduce':
return state - 1;
default:
return state;
}
}
const add = () => ({ type: 'add' });
const reduce = () => ({ type: 'reduce' });
const asyncAdd = () => dispatch => {
setTimeout(() => {
dispatch({ type: 'add' })
}, 2000)
}
export {firstReducer,add,reduce,asyncAdd,}
index.js 入口主文件 创建数据仓库
import React from 'react'
import ReactDOM from 'react-dom'
import ReduxDemo from './ReduxDemo';
import { Provider } from 'react-redux';
import { firstReducer } from './redux-demo/store';
import { createStore, applyMiddleware } from 'redux';
import logger from 'redux-logger';
import thunk from 'redux-thunk';
// 创建数据仓库
const store = createStore(firstReducer, applyMiddleware(thunk, logger));
ReactDOM.render(
<Provider store={store}>
<ReduxDemo></ReduxDemo>
</Provider>, document.getElementById('root')
);
FirstRedux.js 实际使用,绑定到了props上的action。
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { add, reduce, asyncAdd } from './store';
@connect(
state => ({ count: state }),
{ add, reduce, asyncAdd }
)
class FirstRedux extends Component {
render() {
return (
<div>
<h5>第3节、react-redux累加器</h5>
<p>{this.props.count}</p>
<div>
<button onClick={() => this.props.add()}>加1</button>
<button onClick={() => this.props.reduce()}>减1</button>
<button onClick={() => this.props.asyncAdd()}>延时加1</button>
</div>
</div>
)
}
}
export default FirstRedux;