本文已参与「新人创作礼」活动,一起开启掘金创作之路。
原理
redux是对于flux的完美实现,redux和react搭配很完美,但是redux是独立的,并不是基于react使用的
Redux 的工作流程
这是一张大家都看过的图
以下仅为个人理解,可能不准确(从store向下开始)
store是个容器,用于储存数据(state),只能有一个storestate数据,某个状态下的数据react Component组件,通过操作执行action creatorsactionreact Component中的操作,react Component中无法直接获取和修改state,要通过action修改(改变state的唯一方式是通过触发action来修改)dispatch(action)view发出action的方法,他接受一个形参,形参的值为描述action的动作(只发出,不是接受)previousState,actionstore接收到action后,调用reducer传入previousState,action(老状态和action),执行reducesreducers通过store接收action,然后根据action返回新的statenewState返回的新的state,view层通过store.getState获取新的state
安装
npm install --save redux react-redux
创建基础store文件
引入redux中的createStore,通过他创建store文件
import { createStore } from "redux";
const store = createStore(reducer); // reducer在下边代码块中会演示创建
export default store;
然后创建reducer,reducer为store中要存储的数据(是一个function)
function reducer(state = 0, action) {
if (action.type !== "reducer") return state
return action.payload ? action.payload : state
}
state 为存储的数据(上一次传入的值,如果是第一次获取state,默认为0)
action 为调用function 传入的参数
store.js文件整体代码
import { createStore } from "redux";
function reducer(state = 0, action) {
if (action.type !== "reducer") return state
return action.payload ? action.payload : state
}
const store = createStore(reducer); // reducer在下边代码块中会演示创建
export default store;
获取数据 (getState)
在使用时,需要在页面中先引入store文件,然后通过getState获取到store中的数据
import store from "../store/store.js"
...
function getStore () {
console.log(store.getState())
}
...
Action触发 (dispatch)
通过dispatch触发Action来改变store中存储的值
import store from "../store/store.js"
...
function setStore () {
store.dispatch({
type: "reducer",
payload: 10
})
}
// store.getState() // 10
多任务方法 (combineReducers)
按照上边方法,redux只能存储一个值,如果想存储多个,需要 combineReducers 调用一下
import { createStore, combineReducers } from "redux"; // 需要引入 combineReducers
function reducer(state = 0, action) {
if (action.type !== "reducer") return state
return action.payload ? action.payload : state
}
function counter(state = 0, action) {
if (action.type !== "counter") return state
return action.payload ? state + action.payload : state
}
// const store = createStore(reducer); // 之前的写法
const store = combineReducers({
reducer,
counter
})
export default store;
redux中间件 (applyMiddleware)
applyMiddleware 是redux插件默认带的一种方法,为store添加中间件。
applyMiddleware将所有中间件组成一个数组,依次执行
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var store = createStore(reducer, preloadedState, enhancer);
var dispatch = store.dispatch;
var chain = [];
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
};
chain = middlewares.map(middleware => middleware(middlewareAPI));
dispatch = compose(...chain)(store.dispatch);
return {...store, dispatch}
}
}
//执行顺序解析
//中间件数组传入{getState: store.getState,dispatch: (action) => dispatch(action)} =>
//compose合并新中间件数组 并传入dispatch=>
//执行完所有中间件函数后返回store和dispatch
applyMiddlewares 返回的是store 对象
异步处理 (redux-thunk)
通过react-thunk 可以进行异步处理
安装 npm i --save redux-thunk
import thunk from 'redux-thunk' // 引入
...
var store = createStore(rReducers, applyMiddleware(thunk)) // 注册
export default store
异步组件书写方法和同步组件类似,如果是异步,需要返回一个promise对象
function strCounter(state = 'aaa', action) {
if (action.type !== "strCounter") return state
if (action.payload) {
var data = new Promise((resolve, reject) => {
setTimeout(() => {
return '2222'
},10000)
})
return data
} else {
return state
}
}
react-thunk 源码
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
源码来源:简书博主zhangwang