前言
React-Redux 是一个用于管理 React 应用状态的库,它背后有着强大的实现原理。本文简要介绍 React-Redux 的实现原理。
React-Redux 基于两个核心概念:Provider 和 Connect。Provider 组件负责将 Redux 存储(Store)暴露给整个 React 应用。Connect 则是高阶组件,用于连接 React 组件与 Redux Store。当一个组件通过 Connect 连接到 Store 时,它可以订阅 Store 的状态,并在状态发生变化时获得通知。这种连接是通过高阶组件的嵌套来实现的,它使 React 组件能够读取并分发 Redux 的状态。
Redux 的工作原理依赖于发布/订阅模式,每当应用状态发生变化时,Redux 会通知已连接的组件,触发重新渲染。这种数据流的单向性有助于可预测性和可维护性。
React-Redux 的实现原理使得状态管理变得清晰、可测试和高效。它为 React 应用提供了一个强大的状态管理解决方案,有助于构建复杂的前端应用程序。
在看了前面的 React-Redux 之后,这篇文章主要介绍的就是内部的实现过程,为了更好的去了解 React-Redux 内部的工作原理,首先新建一个 connect 目录,存放具体的实现代码,在经过观察我们之前使用 React-Redux 的代码发现在导出的时候是通过调用一个 connect 的方法,所以这里我们也进行实现一下,那么是方法的调用那么内部肯定是封装了一个函数,然后还有就是通过该方法得到的结果也得要是一个组件,不然其它地方无法进行使用。
- 然后我们的实现代码如下
import React from 'react'; import store from '../store/store'; function connect(mapStateToProps, mapDispatchToProps) { return function enhanceComponent(WrappedComponent) { return class Component extends React.PureComponent { constructor(props) { super(props); this.state = { storeState: {...mapStateToProps(store.getState())} } } componentDidMount() { store.subscribe(() => { this.setState({ storeState: {...mapStateToProps(store.getState())} }) }) } componentWillUnmount() { store.unsubscribe(); } render() { return (<WrappedComponent {...this.props} {...mapStateToProps(store.getState())} {...mapDispatchToProps(store.dispatch)}/>) } } } } export default connect;
- 修改 Home.js 修改为我们自己实现的 connect 然后在查看效果
经过如上的一顿操作过后呢,已经实现了将 mapStateToProps
与 mapDispatchToProps
给映射到了 props 当中了,但是尽管如此我们的代码和官方的还是有些不一样的,还是有区别的,我们现在获取 Redux 当中的数据是经过手动导入进行获取的,官方是通过 Provider 传入进来的,所以下面我还会继续将完善一下我们的封装代码。
- 新建 context.js 构建一个全局上下文对象
import React from 'react'; const StoreContext = React.createContext({}); export default StoreContext;
- 修改 index.js 不用官方提供的生产者生产,用我们的全局上下文对象进行生产
import ReactDOM from 'react-dom'; import React from 'react'; import App from './App'; import {BrowserRouter} from 'react-router-dom'; import store from "./store/store"; import StoreContext from "./connect/context"; ReactDOM.render( <StoreContext.Provider value={store}> <BrowserRouter> <App/> </BrowserRouter> </StoreContext.Provider>, document.getElementById('root') );
- 修改 connect.js 将之前从 store 当中获取的代码改造为从我们的全局上下文对象当中进行获取
import React from 'react'; import StoreContext from "./context"; function connect(mapStateToProps, mapDispatchToProps) { return function enhanceComponent(WrappedComponent) { class Component extends React.PureComponent { constructor(props, context) { super(props, context); this.state = { storeState: {...mapStateToProps(this.context.getState())} } } componentDidMount() { this.context.subscribe(() => { this.setState({ storeState: {...mapStateToProps(this.context.getState())} }) }) } componentWillUnmount() { this.context.unsubscribe(); } render() { return (<WrappedComponent {...this.props} {...mapStateToProps(this.context.getState())} {...mapDispatchToProps(this.context.dispatch)}/>) } } Component.contextType = StoreContext; return Component; } } export default connect;
测试的话自行启动项目测试即可,这么做的目的就是以后我们不管什么 React 项目只需要将 connect 当中的内容复制过去就可以实现 Redux 的使用了,而且对项目的依赖很小。