原文收录在github 仓库 (包含小demo) github地址:点这里 react
通用的状态管理辅助工具
,习惯上咱们能够结合ReactJs
来使用,在组件化开发过程当中,组件的数据状态
不得不集中化管理,这也是咱们使用Redux
的缘由之一,是一个数据的容器。习惯上咱们称之为js库
ios
action
顾名思义动做
,行动
行为
,一言以蔽之,它是把数据从应用传到仓库
的一个动做,也就是这个数据仓库git
JS对象es6
格式github
{
type:ADD, // type 字段是约定,你们的约定,表示动做的名字,
index:1,
content:'这是一点内容'
}
复制代码
type
字段表示执行的动做;字符串常量在实际的开发中咱们习惯上是action建立函数typescript
const addAction = (params)=>{
return {
type:ADD,
...params
}
}
复制代码
如今咱们依旧不说store
这个概念,如今动做
有了,可是action
它只是描述了一下这个动做,但并不知道咋更新数据,提到数据,咱们假使redux
{
num:0
}
复制代码
这个简单的js对象
就是数据axios
ACTION是个普通的对象;REDUCER是个普通的函数api
说普通也不普通,js的函数而已app
function(a,b){
console.log(a+b)
}
复制代码
可是没那么简单
干净简单,
// 默认的数据
const initData = {
num:123
}
// reducer
const counterReducer =(state=initData,action)=>{
// 啥也不干,返回传进来的state(此时默认的initData)
return state
}
复制代码
怎么可能啥也不干呢
import { addAction } from "./actions";
// 默认的数据
const initData = {
num: 123
};
// reducer
const counterReducer = (state = initData, action) => {
// 判断传入的动做是什么类型
switch (action.type) {
case addAction:
return Object.assign({}, state, {
...
});
default:
return state;
}
// 啥也不干,返回传进来的state(此时默认的initData)
// return state;
};
复制代码
注意
state
getState()
复制代码
dispatch(action)
复制代码
也就是咱们说的派发一个动做
subscribe(listener)
复制代码
在这个时候,有个问题,前边说的这一切,那咱们该怎么来建立这个仓库呢
yarn add redux
复制代码
这个库里就有方法,也就是咱们常说的redux
import { ADD_TYPE } from './actionTypes'
const addAction = (params)=>{
return {
type:ADD_TYPE,
...params
}
}
export {
addAction
}
复制代码
import { addAction } from "./actions";
// 默认的数据
// reducer
const counterReducer = (state = {num:123}, action) => {
// 判断传入的动做是什么类型
switch (action.type) {
case addAction:
return Object.assign({}, state, action);
default:
return state;
}
// 啥也不干,返回传进来的state(此时默认的initData)
// return state;
};
export {
counterReducer
}
复制代码
import { createStore } from "redux";
import { counterReducer } from "./reducers";
复制代码
const store = createStore(counterReducer);
export default store
复制代码
const handleClick = ()=>{
console.log(`点击了按钮`)
const action = addAction({num:'456'})
store.dispatch(action)
}
复制代码
useEffect(() => {
store.subscribe(()=>{
console.log('-----',store.getState())
})
}, [])
复制代码
const render = ()=>{
ReactDom.render( <App/>, document.querySelector('#root') ) }
// 上来的时候先渲染一次
render()
// 订阅变动,每当数据发生的变化的时候,就从新渲染
store.subscribe(render)
复制代码
经过一个简单的案例,咱们知道一个简易的流程:
action
返回一个对象必须有type属性reducer
响应action t经过return 把数据传回storeredux
这个库来建立一个store 传递写好的reducer
$store.subscribe()
注册监听store.getState()
取值那在如上咱们使用的redux
这个库看起来是没有问题,可是
这一波流的操做在每一个组件都要走一遍,显然是十分繁琐和重复的,这就须要看谁能不能帮帮我,这就是react-redux
若是须要把redux
整合到react
中来使用就须要react-redux
react-redux
redux 官方出品
可以更好的结合react
来管理数据
state
store
做为props
经过context
传递store
中的state
connect
增强const mapStateToProps = (state, ownProps) => {
console.log(state)
return state
// return {
// prop: state.prop
// }
}
复制代码
const mapDispatchToProps = (dispatch, ownProps) => {
return {
sendAction: () => {
dispatch({
type: "ADD_TYPE",
});
},
};
};
复制代码
安装相关的依赖
构建store 和readucer
Provider组件实现
<>
<Provider store = {store}>
<List></List>
<Detail></Detail>
</Provider>
</>
复制代码
import { createStore, combineReducers } from "redux";
// import { counterReducer } from "./reducers";
// import rootReducer from './reducers/index'
import { infoReducer } from "./reducers/infoReducer";
import { listReducer } from "./reducers/listReducer";
const reducer = combineReducers({
infoReducer,
listReducer,
});
// 构建store
const store = createStore(reducer);
export default store;
复制代码
ComA A组件
import React, { Component } from "react";
import { connect } from "react-redux";
class ComA extends Component {
handleClick = () => {
this.props.getInfo();
};
render() {
return (
<div>
{/* <h3>{this.props.}</h3> */}
<button onClick={this.handleClick}>获取信息</button>
</div>
);
}
}
const mapStateToProps = (state, ownProps) => {
console.log(state.infoReducer);
// return {
// prop: state.prop,
// };
// return state
return {
...state.infoReducer,
};
};
const mapDispatchToProps = (dispatch, ownProps) => {
return {
getInfo: () => {
const actionCreator = {
type: "GET_INFO",
};
dispatch(actionCreator);
},
};
};
export default connect(mapStateToProps, mapDispatchToProps)(ComA);
复制代码
ComB
import React, { Component } from "react";
import { connect } from "react-redux";
class ComB extends Component {
handleClick = () => {
this.props.getList();
};
render() {
return (
<div>
<button onClick={this.handleClick}>获取列表</button>
</div>
);
}
}
const mapStateToProps = (state, ownProps) => {
console.log(state.listReducer)
// return state
return {
...state.listReducer
}
};
const mapDispatchToProps = (dispatch, ownProps) => {
return {
getList: () => {
const actionCreator = {
type: "GET_LIST",
};
dispatch(actionCreator);
},
};
};
export default connect(mapStateToProps, mapDispatchToProps)(ComB);
复制代码
infoReducer.js
const info = {
name: "yayxs",
};
const infoReducer = (state = {}, action) => {
switch (action.type) {
case "GET_INFO":
return {
...info,
};
default:
return state;
}
};
export {
infoReducer
}
复制代码
listReducer
const listArr = [
{
id: 1,
con: "耳机",
},
];
const listReducer = (state = {}, action) => {
switch (action.type) {
case "GET_LIST":
return {
listArr: [...listArr],
};
default:
return state;
}
};
export {
listReducer
}
复制代码
无论怎么说,如上说起数据流操做只支持同步的操做,实现异步的话就须要中间件
异步操做
,让反作用的执行更加简单其中源码是这样的
export default function createSagaMiddleware<C extends object>(options?: SagaMiddlewareOptions<C>): SagaMiddleware<C> export interface SagaMiddlewareOptions<C extends object = {}> {
/** * Initial value of the saga's context. */
context?: C
/** * If a Saga Monitor is provided, the middleware will deliver monitoring * events to the monitor. */
sagaMonitor?: SagaMonitor
/** * If provided, the middleware will call it with uncaught errors from Sagas. * useful for sending uncaught exceptions to error tracking services. */
onError?(error: Error, errorInfo: ErrorInfo): void
/** * Allows you to intercept any effect, resolve it on your own and pass to the * next middleware. */
effectMiddlewares?: EffectMiddleware[]
}
复制代码
import createSagaMiddleware from "redux-saga";
复制代码
const store = createStore(sagaReducer, {}, applyMiddleware(sagaMiddleware));
复制代码
sagaMiddleware.run(defSage);
复制代码
takeEvery
takeLatest
throttle
SagaCom
handleClick = (type) => {
switch (type) {
case "takeEvery":
this.props.dispatch({
type: "takeEvery",
});
break;
case "takeLatest":
this.props.dispatch({
type: "takeLatest",
});
break;
case "throttle":
this.props.dispatch({
type: "throttle",
});
break;
default:
break;
}
};
复制代码
import {
takeEvery,
takeLatest,
throttle,
select,
call,
} from "redux-saga/effects";
import axios from "axios";
export function* defSage() {
yield takeEvery("takeEvery", function* () {
const state = yield select((state) => state.payload);
const res = yield call(
axios.post,
`http://rap2.taobao.org:38080/app/mock/249413/mock-api/v1/users/login`,
{
...state,
}
);
console.log(res);
});
// 最后的一次,取消正在运行中
yield takeLatest("takeLatest", function* () {
const state = yield select((state) => state.payload);
const res = yield call(
axios.post,
`http://rap2.taobao.org:38080/app/mock/249413/mock-api/v1/users/login`,
{
...state,
}
);
console.log(res);
});
/** * 毫秒值 */
yield throttle(0, "throttle", function* () {
const state = yield select((state) => state.payload);
const res = yield call(
axios.post,
`http://rap2.taobao.org:38080/app/mock/249413/mock-api/v1/users/login`,
{
...state,
}
);
console.log(res);
});
}
复制代码
详细的api 用法能够参考官方文档
action
reducer
匹配对应的action 若是是一部的action 直接把数据返回takeEvery
来进行监听takeEvery
takeLatest
throttle
在底层有什么区别?感谢你看到这,不妨给个星星,感谢