React Redux 原理分析

108 阅读1分钟

1. 为什么应该使用 React-Redux

  • React-Redux 是 React 的官方 Redux UI 绑定库。如果想要同时使用 Redux 和 React,你也应该使用

2. React Redux API原理

2.1.connect

  • connect 是 React-Redux 提供的一个高阶组件,用来连接 React 组件与 Redux store,通常用于类组件。它会自动将 Redux store 中的 state 和 dispatch 方法作为 props 传递给组件。
  • connect.jsx
function connect(mapStateProps, mapDispatchProps) {
	return function (OldComponent) {
		return class extends React.Component {
			static contextType = ReactReduxContext;
			constructor(props, context) {
				super(props);
				this.store = context.store;
				const { getState, subscribe, dispatch } = context.store;
				this.state = mapStateProps(getState());
				this.dispatch = context.store.dispatch;
				this.unsubscribe = subscribe(() => {
					this.setState(mapStateProps(getState()));
				});
				let dispatchProps;
				if (typeof mapDispatchProps === 'function') {
					dispatchProps = mapDispatchProps(dispatch);
				} else if (!dispatchProps) {
					dispatchProps = {
						dispatch: dispatch,
					};
				} else {
					dispatchProps = bindActionCreators(
						mapDispatchProps,
						dispatch
					);
				}
				this.dispatchProps = dispatchProps;
			}
			componentWillUnmount() {
				this.unsubscribe();
			}
			render() {
				console.log(this);
				return (
					<OldComponent
						{...this.props}
						{...this.state}
						{...this.dispatchProps}
					></OldComponent>
				);
			}
		};
	};
}
export default connect;

2.2.Provider

import React, { Component } from 'react';
import ReactReduxContext from './Context';
export default class Provider extends Component {
	constructor(props) {
		super(props);
	}
	render() {
		return (
			<ReactReduxContext.Provider value={{ store: this.props.store }}>
				{this.props.children}
			</ReactReduxContext.Provider>
		);
	}
}

2.3.Context

import React from 'react'

export const ReactReduxContext = React.createContext(null)

export default ReactReduxContext

2.4.useStore

import ReactReduxContext from '../Context';
import { useContext } from 'react';
function useStore() {
	const { store } = useContext(ReactReduxContext);
	return store;
}

export default useStore;

2.5.useSelector

import ReactReduxContext from '../Context';
import React from 'react';
export default function useSelector(selector, options) {
	// 获取当前对象的上下文store
	const { store } = React.useContext(ReactReduxContext);
	// 获取所有的存储数据
	const state = store.getState();
	// 拿到当前需要用到的数据
	const selectedState = selector(state);
	const [, forceRender] = React.useReducer((s) => s + 1, 0); // 强制组件重新渲染的 reducer

	// 重新定义store 改变重新渲染组件
	React.useEffect(() => {
		const unsubscribe = store.subscribe(() => {
			forceRender(); // 通过调用 reducer 强制重新渲染组件
		});
		return () => {
			unsubscribe();
		};
	}, [store]);
	return selectedState;
}

2.6.useDispatch

import ReactReduxContext from '../Context';
import React from 'react';
export default function useDispatch(a) {
	// 通过 useContext 获取 ReactReduxContext.Provider 提供的 value
	const { store } = React.useContext(ReactReduxContext);

	// 返回 Redux store 的 dispatch 函数
	return store.dispatch;
}

2.7.useBoundDispatch

import { useContext } from 'react';
import ReactReduxContext from '../Context';
import bindActionCreators from '../../redux/bindActionCreators';
function useBoundDispatch(actions) {
	const { store } = useContext(ReactReduxContext);
	const boundDispatch = bindActionCreators(actions, store.dispatch);
	return boundDispatch;
}
export default useBoundDispatch;