react深入2 - react-redux
1.react-redux使用
1.1 安装
npm i redux
npm i react-redux
1.2 创建一个store
// src\store\index.tsimport { createStore, Action } from 'redux';function countReducer(count:number = 0, action:Action) {switch (action.type) {case 'ADD':return count + 1;case 'MINUS':return count - 1;default:return count;}
}export default createStore(countReducer);
1.3 Provider 提供给全局组件使用
// src\main.tsximport React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import store from './store';
import ClassPage from './view/ClassPage';function App() {return (<div><Provider store={store}><ClassPage /></Provider></div>);
}render(<App />, document.getElementById('root'));
1.4 子class 组件使用
// src\view\ClassPage.tsximport React, { Component } from 'react';
import { connect } from 'react-redux';// eslint-disable-next-line react/prefer-stateless-function
class ClassPage extends Component {render(): React.ReactNode {console.log(this.props);// eslint-disable-next-line react/prop-typesconst { count, add, minus } = (this.props as any);return (<div><p>{count}</p><button onClick={() => add()} type="button">add</button><button onClick={() => minus()} type="button">minus</button></div>);}
}export default connect((count:number) => ({ count }),(dispatch) => {const add = () => dispatch({ type: 'ADD' });const minus = () => dispatch({ type: 'MINUS' });return {add,minus,dispatch,};},
)(ClassPage);
2.实现自己的 react-redux
// src\react-redux\index.tsximport React, { useContext, useLayoutEffect, useReducer } from 'react';// 创建一个用于存放store的上下文
const Context = React.createContext(undefined);
const StoreProvider = Context.Provider;export function Provider({ store, children }:any) {return <StoreProvider value={store}>{children}</StoreProvider>;
}function useForceUpdate() {const [,forceUpdate] = useReducer((i) => i + 1, 0);return () => forceUpdate();
}
// eslint-disable-next-line max-len
export const connect = (mapStateToProps:any, mapDispatchToProps:any) => (WrappedComponent:any) => (props:any) => {const store = useContext(Context) as any;const forceUpdate = useForceUpdate();const stateProps = mapStateToProps(store.getState());let dispatchProps:any = {};if (typeof mapDispatchToProps === 'function') {dispatchProps = mapDispatchToProps(store.dispatch);} else {// eslint-disable-next-line no-restricted-syntaxfor (const key in mapDispatchToProps) {if (Object.prototype.hasOwnProperty.call(mapDispatchToProps, key)) {dispatchProps[key] = (...args:any) => store.dispatch(mapDispatchToProps[key](...args));}}}useLayoutEffect(() => {const unsubscribe = store.subscribe(() => {forceUpdate();});return () => unsubscribe();}, [forceUpdate, store]);// eslint-disable-next-line react/jsx-props-no-spreadingreturn <WrappedComponent {...props} {...stateProps} {...dispatchProps} />;
};export default {};
3.hook 中使用 react-redux
import React, { useCallback } from 'react';
import { useSelector, useDispatch } from 'react-redux';export default function FunctionPage() {const num = useSelector((count:number) => count);const dispatch = useDispatch();const add = useCallback(() => {dispatch({type: 'ADD',});}, [dispatch]);return (<div><p>{num}</p><button onClick={() => add()} type="button">add</button></div>);
}
4 hooks useSelector useDispatch实现
// src\react-redux\index.tsx// hooks
export function useSelector(selector:any) {const forceUpdate = useForceUpdate();const store = useContext(Context) as any;const selectorState = selector(store.getState());useLayoutEffect(() => {const unsubscribe = store.subscribe(() => {forceUpdate();});return () => unsubscribe();}, [forceUpdate, store]);return selectorState;
}export function useDispatch() {const store = useContext(Context) as any;return store.dispatch;
}
源码
© 著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务

喜欢的朋友记得点赞、收藏、关注哦!!!