/*
createStore传入reducer和applyMiddleware;
若存在中间件,先将createStore中的方法传入中间件进行二次封装后返回一个新的createStore
最后将reducer传入createStore
若不存在中间件,则直接将reducer传入createStore
定义一个currentState存储当前状态
定义一个currentListeners 存储回调函数
三个方法:getState subscribe dispatch
getState 获取store中的state;直接返回当前状态currentState
subscribe 订阅 直接将传入的回调函数push进currentListeners
dispatch 将currentState和action传入reducer返回新的state复制给
currentState并执行回调函数
*/
export function createStore(reducer, enhancer) {
if (enhancer) {
return enhancer(createStore)(reducer)
}
// 保存状态
let currentState = undefined;
// 回调函数
let currentListeners = [];
function getState() {
return currentState
}
function subscribe(listener) {
currentListeners.push(listener)
}
function dispatch(action) {
currentState = reducer(currentState, action)
console.log(currentState);
currentListeners.forEach(v => v())
return action
}
dispatch({ type: '@IMOOC/KKB-REDUX' })
return { getState, subscribe, dispatch }
}
// applyMiddleware实现
/*
我理解的中间件是先改变createStore中的方法并返回新的createStore,
在执行createStore(reducer)
*/
export function applyMiddleware(...middlewares) {
return createStore => (...arg) => {
const store = createStore(...arg);
// 先获取原有的API传入中间件改造
const midApi = {
getState: store.getState,
dispatch: store.dispatch
};
// 将API传入中间件
const chain = middlewares.map(mv => mv(midApi));
// 依次执行中间件进行API改造
const dispatch = compose(...chain)(store.dispatch);
// 返回合并后原有的API和改造后的API
return {
...store,
dispatch
}
}
}
function compose(...funs) {
const length = funs.length;
if (length === 0) {
return arg => arg
}
if (length === 1) {
return funs[0]
}
return funs.reducer((left, right) => (...props) => right(left(...props)))
}
thunk中间件
/*
将dispatch进行再次封装,返回一个dispatch方法,给方法接收一个参数action
若action为函数,则将dispatch和getstate作为参数传入action中返回
若action不是函数,则直接返回dispatch(action) (此时相当于未改造dispatch)
*/
function thunk({ dispatch, getState }) {
return dispatch => action => {
if (typeof action === 'function') {
return action(dispatch, getState)
}
return dispatch(action)
}
}
react-redux通过hooks实现
主要是context实现,context创建Provider和useContext获取context值
/*
Provider 实现:
定义一个Provider组件,返回一个组件
<Context.Provider value={props.store}> {props.children}</Context.Provider>
将Provider 包裹的children组件原样输出,store值传递下一层
connect 实现:
传入myState、myDispatch,和一个组件,将myState、myDispatch和传入组件的props合并后,
返回一个组件,带有合并后的props
myState传入state返回state
myDispatch中的每个元素传入dispatch执行后返回
*/
import React, { useContext, useState, useEffect } from 'react'
const Context = React.createContext();
export const Provider = (props) => {
// console.log(props.store);
return <Context.Provider value={props.store}>
{props.children}
</Context.Provider>
}
export const connect = (myState = state => state, myDispatch = {}) => {
return Cmp => {
return () => {
//获取到传入的数据,包含getState,dispatch,subscribe方法
const store = useContext(Context);
const getProps = () => {
const stateProps = myState(store.getState());
const dispatchProps = bindActionCreators(myDispatch, store.dispatch);
return {
...stateProps,
...dispatchProps
}
};
useEffect(() => {
store.subscribe(() => {
setProps({
...props,
...getProps()
})
})
}, [])
const [props, setProps] = useState({ ...getProps })
return <Cmp {...props} />
}
}
}
function bindActionCreators(creators, dispatch) {
return Object.keys(creators).reduceRight((res, item) => {
res[item] = bindActionCreator(creators[item], dispatch)
return res
}, {})
}
function bindActionCreator(creator, dispatch) {
return (...arg) => dispatch(creator(...arg))
}