顾名思义react-redux是对于redux的延伸以及功能的扩展具体,那我们先来说说redux目前存在的问题
redux目前存在的问题
1、每个组件都需要进行订阅并且进行强制更新操作
2、如果要获取store状态或者执行dispatch就需要在组件内引入store文件,非常繁琐以及不好维护
react-redux提供了两个API
1、Provider 为后代组件提供store
2、Connect 为组件提供数据和变更方法
react-redux的使用
// index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import store from "./store/";
import {Provider} from "react-redux";
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
1、在类组件中的使用
//组件中的应用
import React, {Component} from "react";
import {connect} from "react-redux";
@connect(
// mapStateToProps 把state放到props上一份
state => {
return {count: state.count};
},
// mapDispatchToProps object|function 把dispatch放到props上一份
{
add: () => ({type: "ADD"}),
minus: () => ({type: "MINUS"})
}
)
class ReactReduxPage extends Component {
render() {
const {count, dispatch, add, minus} = this.props;
return (
<div>
<h3>ReactReduxPage</h3>
<p>{count}</p>
<button onClick={() => dispatch({type: "ADD", payload: 100})}>
dispatch add
</button>
<button onClick={add}> add</button>
<button onClick={minus}> minus</button>
</div>
);
}
}
export default ReactReduxPage;
2、在函数组件中的使用
import React, {useCallback} from "react";
import {useSelector, useDispatch} from "react-redux";
export default function ReactReduxHookPage(props) {
const count = useSelector(({count}) => count);
const dispatch = useDispatch();
const add = useCallback(() => {
dispatch({type: "ADD"});
}, []);
return (
<div>
<h3>ReactReduxHookPage</h3>
<p>{count}</p>
<button onClick={add}>add</button>
</div>
);
}
从上面的不同类型组件中的使用可以看出react-redux即提供了在类组件中的mapStateToProps以及mapDispatchToProps,还有函数组件中的两个钩子函数useSelector以及useDispatch
针对类组件的源码剖析
import React, {useContext, useReducer, useEffect, useLayoutEffect} from "react";
const Context = React.createContext();
export const connect = (
mapStateToProps = state => state,
mapDispatchToProps
) => WrappedComponent => props => {
//props是WrappedComponent的属性值
const store = useContext(Context);
const {getState, dispatch, subscribe} = store;
// todo 获取state
const stateProps = mapStateToProps(getState());
let dispatchProps = {
dispatch
};
if (typeof mapDispatchToProps === "function") {
dispatchProps = mapDispatchToProps(dispatch);
} else if (typeof mapDispatchToProps === "object") {
dispatchProps = bindActionCreators(mapDispatchToProps, dispatch);
}
// 函数组件实现forceUpdate的方法
const [ignored, forceUpdate] = useReducer(x => x + 1, 0);
useLayoutEffect(() => {
const unsubscribe = subscribe(() => {
forceUpdate();
});
return () => {
if (unsubscribe) {
unsubscribe();
}
};
}, [store]);
return <WrappedComponent {...props} {...stateProps} {...dispatchProps} />;
};
export function Provider({children, store}) {
return <Context.Provider value={store}>{children}</Context.Provider>;
}
针对函数组件的源码剖析
export function Provider({children, store}) {
return <Context.Provider value={store}>{children}</Context.Provider>;
}
function bindActionCreator(creator, dispatch) {
return (...arg) => dispatch(creator(...arg));
}
export function bindActionCreators(creators, dispatch) {
let obj = {};
for (let key in creators) {
obj[key] = bindActionCreator(creators[key], dispatch);
}
return obj;
}
export function useSelector(selector) {
const store = useStore();
const {getState, subscribe} = store;
const selectState = selector(getState());
const [ignored, forceUpdate] = useReducer(x => x + 1, 0);
useLayoutEffect(() => {
const unsubscribe = subscribe(() => {
forceUpdate();
});
return () => {
if (unsubscribe) {
unsubscribe();
}
};
}, [store]);
return selectState;
}
export function useDispatch() {
const store = useStore();
return store.dispatch;
}
function useStore() {
const store = useContext(Context);
return store;
}