[redux]core
[redux]enhancer
redux-thunk 原本action只能接受plain对象,现在可以接受function[redux]applyMiddleware
[react-redux]core
在redux基础上(getState,dispatch,subscribe)

小结
redux核心功能:提供getState,dispatch,subscribe 这几个api给开发者使用
yarn add redux 指定4.1.2版本
创建store
dispatch,subscribe,getState 给组件使用组件调用
中间件
dispatch getState 能力
功能:
自定义redux
实现 createStore,dispatch,subscribe,getState
创建简单版store:
创建实用版store:
组件调用:不变同上
简单版

实用版

// 原本调用dispatch,只接受 action 对象
const doAdd = () =>{
store.dispatch({type: 'ADD'});
}
// 希望改写dispatch方法,使其接受 function 参数
const doAdd = () =>{
store.dispatch(dispatch =>{
setTimeout(()=>{
console.log('setTimeout');
dispatch({type: 'ADD'});
},1000);
});
}
// 原本fn, 期望返回值包含参数
function fn(a){
return {pow: a*a}
}
// 做法1:直接
function proxyFn(a){
const result = fn(a);
return {...result, a}
}
console.log("fn(2): ", JSON.stringify(fn(2))); // fn(2): {"pow":4}
console.log("proxyFn(2): ", JSON.stringify(proxyFn(2))); // proxyFn(2): {"pow":4,"a":2}
// 做法2:使用hoc
function fn(a,enhancer){
if(enhancer){
return enhancer(fn)(a);
}
return {pow: a*a}
}
function hoc(fn){
return function(a){
let result = fn(a);
// return result; // 这样,与fn本身等价
return {...result,a} // 这样,调整了fn返回值
}
}
console.log("fn(2): ", JSON.stringify(fn(2))); // fn(2): {"pow":4}
console.log("fn(2,hoc): ", JSON.stringify(fn(2,hoc))); // fn(2,hoc): {"pow":4,"a":2}
branch: fea-add-redux
源码: https://github.com/reduxjs/redux-thunk/blob/v2.3.0/src/index.js
// 添加 redux-thunk
// yarn add redux-thunk
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
function counterReducer(state = { num: 0 }, action) {
// ...
}
export default createStore(counterReducer, applyMiddleware(thunk))
// 使用 redux-thunk
const doAdd = () =>{
// store.dispatch({type: 'ADD'});
// 通过点击 redux-thunk 可以支持 dispatch 参数为 function
store.dispatch(dispatch =>{
setTimeout(()=>{
console.log('setTimeout');
dispatch({type: 'ADD'});
},1000);
});
}
// 期望:希望先后执行add 和 multi
function add(x){
return x+1;
}
function multi(x){
return x*2;
}
function compose(f,g){
return function(x){
// 从右往左执行
return f(g(x));
}
}
console.log("multi(add(1)):", multi(add(1)) );
console.log("compose(multi,add)(1): ", compose(multi,add)(1));
// 期望:如果compose入参个数不固定
function add(x){
return x+1;
}
function multi(x){
return x*2;
}
function compose(...funs){
if(funs.length === 0 ){
return args => args
}else if(funs.length === 1){
return funs[0]
}else{
// 调用 reduce 的数组 至少有2个元素。
// 因为如果funs个数为0,会报错,个funs数为1,不执行回调,直接返回初始值
// prev 默认取 funs[0], cur 默认取 funs[1]
return funs.reduce((prev,cur)=>{
return (...args) => prev(cur(...args));
})
}
}
// 2*(1+(2*(1+1))) = 10
console.log("multi(add(multi(add(1)))): ", multi(add(multi(add(1))))); // multi(add(multi(add(1)))): 10
console.log("compose(multi,add,multi,add)(1)", compose(multi,add,multi,add)(1)); // compose(multi,add,multi,add)(1) 10
// other test
console.log("compose()(1,2,3,4)", compose()(1,2,3,4)); // compose()(1,2,3,4) 1
console.log("compose(multi)(1)", compose(multi)(1)); // compose()(1,2,3,4) 2
参考 redux-thunk
// 自定义middleware,在每次执行dispatch时触发log操作
function createSmallLogMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
console.log('smallLog action:',JSON.stringify(action));
return next(action);
};
}
const smallLog = createSmallLogMiddleware();
smallLog.withExtraArgument = createSmallLogMiddleware;

react-redux核心功能:在redux基础上(getState,dispatch,subscribe)
官方使用
// [1] 添加依赖
// yarn add react-redux
// [2] 使用 Provider组件
// Provider 直接与 store 关联,并将store注入全部组件
import {Provider} from "react-redux";
<Provider store={store}>
{/*...*/}
</Provider>
// [3] 使用 connect 方法
// connect 只与 普通组件关联
import { connect } from 'react-redux';
function Top(props){
const { num, add, sub } = props;
// ....
}
const mapStateToProps = (state) =>{
return {
num: state.num
}
}
const mapDispatchToProps = (dispatch) =>{
return {
add: () => dispatch({type: 'ADD'}),
sub: () => dispatch({type: 'SUB'}),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Top);
// 输入: props.store
// 输出: 渲染子组件的新组件
export const Provider = (props) => {
const { store } = props;
// store: {dispatch, subscribe, getState}
return (
<>
{props.children}
</>
)
}
// 输入: mapStateToProps, mapDispatchToProps, WrapComponent
// 输出: 关联state的新组件
export const connect = (mapStateToProps, mapDispatchToProps) => (WrapComponent) =>{
return () => {
return (
<WrapComponent></WrapComponent>
)
}
}
const StoreContext = React.createContext("");
export const Provider = (props) => {
const { store } = props;
return (
<StoreContext.Provider value={store}>
{props.children}
</StoreContext.Provider>
)
}
export const connect = (mapStateToProps, mapDispatchToProps) => (WrapComponent) => {
return () => {
const store = useContext(StoreContext); // store: {dispatch, subscribe, getState}
return (
<WrapComponent></WrapComponent>
)
}
}
export const connect = (mapStateToProps, mapDispatchToProps) => (WrapComponent) => {
return (props) => { // component own props
const [allProps, setAllProps] = useState({});
const store = useContext(StoreContext);
const { getState, dispatch, subscribe } = store;
useEffect(() => {
update(); // first render
subscribe(update); // when store state change, rerender
}, []);
const update = () =>{
// mapStateToProps ok
const stateProps = mapStateToProps(getState());
// mapDispatchToProps ok
// 此处只考虑 mapDispatchToProps 为函数类型,实际也可以是对象,这里省略处理
const dispatchProps = mapDispatchToProps(dispatch);
// allProps
const allProps = {...props, ...stateProps, ...dispatchProps};
setAllProps(allProps);
}
return (
<WrapComponent {...allProps}></WrapComponent>
)
}
}
redux 4.1.2 可以使用 createStore
redux 4.2.0 configureStore 代替 createStore
redux实际使用版本查看 node_modules/redux/package.json