![](https://img-blog.csdnimg.cn/img_convert/c64320d4ceaa446b3673dcfc9d480d12.png)
createStore
作用
创建一个包含程序完整 state 树的 Redux store 。 应用中应有且仅有一个 store。Store 就是用来维持应用所有的 state 树 的一个对象。 改变 store 内 state 的惟一途径是对它 dispatch 一个 action
(reducer, enhancer) => store
reducer
函数签名:(state, action) => newState
state是初始状态值
action是描述应用变化的普通对象
newState是最新的状态值
作用
接收当前 state 值和描述“发生了什么”的 action 对象,它返回一个新的 state 值
例子
function counterReducer(state = { value: 0 }, action) {
switch (action.type) {
case 'counter/incremented':
return { value: state.value + 1 }
case 'counter/decremented':
return { value: state.value - 1 }
default:
return state
}
}
enhancer
函数签名:(createStore) => reducer => store
作用
一个组合 store creator 的高阶函数,返回一个新的强化过的 store creator
例子
import thunk from "redux-thunk"
import logger from "redux-logger"
import promise from "redux-promise"
const store = createStore(countReducer, applyMiddleware(promise, thunk, logger))
store
一个对象包含以下三个方法
getState
函数签名:() => state
作用:返回应用当前的 state 树,它与 store 的最后一个 reducer 返回值相同
subscribe
函数签名:(listener) => unsubscribe
listener:每当 dispatch action 的时候都会执行的回调函数
unsubscribe:调用后解绑对应的listener
作用:添加一个变化监听器,每当 dispatch action 的时候就会执行,返回一个可以解绑变化监听器的函数。可以使用 subscribe() 来更新 UI 以响应 state 的更改
dispatch
函数签名:(action) => ()
作用
分发 action,会使用当前 getState() 的结果和传入的 action 以同步方式的调用 store 的 reduce 函数。这是触发 state 变化的惟一途径
变化监听器listener会被触发
使用示例
function counterReducer(state = { value: 0 }, action) {
switch (action.type) {
case 'counter/incremented':
return { value: state.value + 1 }
case 'counter/decremented':
return { value: state.value - 1 }
default:
return state
}
}
const store = createStore(counterReducer)
store.subscribe(() => console.log(store.getState()))
store.dispatch({ type: 'counter/incremented' }) // {value: 1}
store.dispatch({ type: 'counter/incremented' }) // {value: 2}
store.dispatch({ type: 'counter/decremented' }) // {value: 1}
简化源码
export default function createStore(reducer, enhancer) {
if (enhancer) {
// enhancer用来增强dispatch函数,怎么增强呢,在createStore中增强dispatch
return enhancer(createStore)(reducer) // 柯里化
}
let state
const listeners = [] // 用set存储应该也行
function getState() {
return state
}
function subscribe(listener) {
listeners.push(listener)
return () => {
const index = listeners.indexOf(listener)
if (index !== -1) {
listeners.splice(index, 1)
}
}
}
function dispatch(action) {
state = reducer(state, action)
listeners.forEach(listener => listener())
}
dispatch({ type: Symbol("init") }); // 初始化state reducer可能传了state默认值
return {
getState,
subscribe,
dispatch
}
}
compose
作用
从右到左来组合多个函数,后一个函数的返回值是前一个函数的参数
使用示例
const fn1 = (arg) => {
console.log("fn1:", arg);
return arg + 1
}
const fn2 = (arg) => {
console.log("fn2:", arg);
return arg + 1
}
const fn3 = (arg) => {
console.log("fn3:", arg);
return arg + 1
}
console.log(compose(fn1, fn2, fn3)(0));
// fn3: 0
// fn2: 1
// fn1: 2
// 3
简化源码
export default function compose(...funcs) {
if (funcs.length === 0) {
return (arg) => arg;
}
if (funcs.length === 1) {
return funcs[0];
}
return funcs.reduce(
(a, b) =>
(...args) =>
a(b(...args))
);
}
applyMiddleware
作用
应用中间键增强dispatch,例如让dispatch支持异步、支持函数形式调用等等
(...middlewares) => createStore
middleware
函数签名:({ getState, dispatch }) => next => action
next:增强后的dispatch
action:增强版dispatch的传参
作用:包装 store 的 dispatch 方法来达到你想要的目的
常见的redux中间键
redux-promise
作用:支持 dispatch 一个异步的 Promise action
简化源码
function promise({ getState, dispatch }) {
// next就是增强后的dispatch action则是增强版dispatch的传参
return (next) => (action) => {
// console.log("^^^^^^^^^^^^promise middleware execute");
if (!(action instanceof Promise)) {
return next(action);
}
action
.then((payload) => {
return dispatch(payload);
})
.catch((err) => {
console.error(err);
});
};
}
redux-thunk
作用:支持 dispatch function
简化源码
function thunk({ getState, dispatch }) {
// next就是增强后的dispatch action则是增强版dispatch的传参
return (next) => (action) => {
// console.log("************thunk middleware execute");
if (typeof action !== "function") {
return next(action);
}
return action(dispatch, getState);
};
}
redux-logger
作用:支持打印调用dispatch前后的状态值
简化源码
function logger({ getState, dispatch }) {
// next就是增强后的dispatch action则是增强版dispatch的传参
return (next) => (action) => {
console.log("------------");
const prevState = getState();
console.log("prev state", prevState);
console.log("action ", action);
// 调用增强后的dispatch,更新state的值
const returnValue = next(action);
const nextState = getState();
console.log("next state", nextState);
console.log("------------");
return returnValue;
};
}
使用示例
import React, { Component } from "react";
import thunk from "redux-thunk"
import logger from "redux-logger"
import promise from "redux-promise"
const store = createStore(countReducer, applyMiddleware(promise, thunk, logger))
export default class ReduxPage extends Component {
componentDidMount() {
// 告诉redux,一旦state变化(一旦执行dispatch函数),就执行的事件
this.unsubscribe = store.subscribe(() => {
this.forceUpdate();
});
}
componentWillUnmount() {
this.unsubscribe();
}
add = () => {
store.dispatch({ type: "ADD" });
};
minus = () => {
// setTimeout(() => {
// store.dispatch({ type: "MINUS" });
// }, 1000);
store.dispatch((dispatch, getState) => {
setTimeout(() => {
dispatch({ type: "MINUS" });
}, 1000);
});
};
promiseMinus = () => {
store.dispatch(
Promise.resolve({
type: "MINUS",
payload: 100,
})
);
};
mixing = () => {
debugger
store.dispatch((dispatch, getState) => {
setTimeout(() => {
dispatch(Promise.resolve({
type: "ADD",
payload: 100
}))
}, 1000)
})
}
render() {
return (
<div>
<h3>ReduxPage</h3>
<p>{store.getState()}</p>
<button onClick={this.add}>add</button>
<button onClick={this.minus}>minus</button>
<button onClick={this.promiseMinus}>promiseMinus</button>
<button onClick={this.mixing}>异步+Promise</button>
</div>
);
}
}
简化源码
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer) => {
const store = createStore(reducer)
const { dispatch } = store
const midAPI = {
getState: store.getState,
dispatch: (action, ...args) => dispatch(action, ...args)
}
// 参考每个中间键的传参 就是这个midAPI { getState, dispatch }
const middlewareChain = middlewares.map((middleware) => middleware(midAPI))
// 新版的dispatch要用到聚合函数,前一个函数的返回值是后一个函数的传参,达到增强dispatch函数的目的
dispatch = compose(...middlewareChain)(dispatch)
return {
...store,
dispatch
}
}
}
combineReducers
作用
把一个由多个不同 reducer 函数作为 value 的 object,合并成一个最终的 reducer 函数,然后就可以对这个 reducer 调用 createStore 方法
(reducers) => reducer
reducers
多个reducer函数
reducer
合并后的 reducer 可以调用各个子 reducer,并把它们返回的结果合并成一个 state 对象
使用示例
function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return state.concat([action.text])
default:
return state
}
}
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
const reducer = combineReducers({
todos,
counter
})
let store = createStore(reducer)
console.log(store.getState())
// {
// counter: 0,
// todos: []
// }
store.dispatch({
type: 'ADD_TODO',
text: 'Use Redux'
})
console.log(store.getState())
// {
// counter: 0,
// todos: [ 'Use Redux' ]
// }
简化源码
注意:需要判断新的state是否有更新,如果没有则返回旧的state
export default function combineReducers(reducers) {
// 返回值应该也是一个reducer (prevState, action) => nextState 并且prevState的默认值是对象{}
return (state = {}, action) => {
// 我们需要判断state是否改变,改变了才进行订阅更新
const nextState = {}
let hasChanged = false
for (const key in reducers) {
const reducer = reducers[key]
nextState[key] = reducer(state[key], action)
// 判断新旧对象属性值是否改变
hasChanged = hasChanged || nextState[key] !== state[key]
}
// 判断新旧state对象 属性长度是否一致 {a: 1, b: 1} {a: 1}
hasChanged = hasChanged || Object.keys(state).length !== Object.keys(nextState).length
return hasChanged ? nextState : state
}
}
bindActionCreators
作用
把一个 value 为不同 action creator 的对象,转成拥有同名 key 的对象。同时使用 dispatch 对每个 action creator 进行包装,以便可以直接调用它们
(actionCreators, dispatch) => creators
actionCreators
可以是一个action creator,也可以是一个value是action creator的对象
Action Creator就是一个创建 action 的函数,或者说是一个创建 action 的工厂
dispatch
一个由 Store 实例提供的 dispatch 函数
creators
对象的 value 都是会直接 dispatch 原 action creator 返回的结果的函数
使用示例
点击add和minus按钮也会触发dispatch函数并传入对应的action逻辑
export default connect(
({ count }) => {
return { count };
},
(dispatch) => {
const creators = {
add: () => ({type: "ADD"}),
minus: () => ({type: "MINUS"}),
}
creators = bindActionCreators(creators, dispatch)
return { dispatch, ...creators}
}
)(
class ReactReduxPage extends Component {
render() {
console.log("props", this.props);
const {
count,
dispatch,
add,
minus
} = this.props;
return (
<div>
<h3>ReactReduxPage</h3>
<button onClick={() => dispatch({type: "ADD"})}>dispatch{count}</button>
<button onClick={() => add()}>add{count}</button>
<button onClick={() => minus()}>minus{count}</button>
</div>
);
}
}
);
简化源码
export function bindActionCreators(actionCreators, dispatch) {
const creators = {}
for (const key in actionCreators) {
const creator = actionCreators[key]
creators[key] = (...args) => dispatch(creator(...args))
}
return creators
}
参考链接: