如何手写react-redux中的connect函数

在react学习中,redux是比较难理解的一个点,今天我们就深入了解一下如何用redux来实现react-redux中connect函数从而便于理解和使用react-redux。
1.什么是redux

官方解释:redux 是 js 应用的可预测状态的容器。 可以理解为全局数据状态管理工具(状态管理机),用来做组件通信等。

2.为什么使用redux

当没有使用redux时兄弟组件间传值将很麻烦,代码很复杂冗余。使用redux定义全局单一的数据Store,可以自定义Store里面存放哪些数据,整个数据结构也是自己清楚的。

3.redux结构图

如何手写react-redux中的connect函数_第1张图片

action:事件,它本质上是JavaScript的普通对象,它描述的是“发生了什么”。action由type:string和其他构成。

reducer:一个监听器,只有它可以改变状态。是一个纯函数,它不能修改state,所以必须是生成一个新的state。在default情况下,必须返回旧的state。

store:一个类似数据库的存储(或者可以叫做状态树),需要设计自己的数据结构来在状态树中存储自己的数据。

4.如何用redux实现react-redux中的connect函数

首先看一下目录结构:

如何手写react-redux中的connect函数_第2张图片

再看一下src/index.js中的代码结构:

import React, {Fragment} from 'react'
import Calculate from "./components/Calculate";

function App(props) {
    return(
        
        	
        
    )
}
export default App;

进入store目录中的中查看src/store/index.jsstore就是整个项目保存数据的地方,并且只能有一个。创建store就是把所有reducer给它。

//创建store对象
import {createStore} from 'redux'
import reducer from './reducer'

const store = createStore(reducer)
export default store

其中引入了reducer,接着查看src/store/reducer.js,

import {
    INCREMENT,
    DECREMENT
} from "./action-types";

const initState = {
    count: 1
}
function change(state = initState, action) {
    switch (action.type) {
        case INCREMENT:{
            return {...state, count: state.count + action.number}
        }
        case DECREMENT:{
            return {...state, count: state.count - action.number}
        }
        default:{
            return {...state}
        }
    }
}

export default change

这里因为只是演示,就直接export default了,其中引入了action-types中的命名,进入查看src/store/action-types.js

//简单导出命名
export const INCREMENT = 'INCREMENT'
export const DECREMENT = 'DECREMENT'

最后查看src/store/action.js中的代码结构, redux将每一个更改动作描述为一个action,要更改state中的内容,你需要发送action。一个action是一个简单的对象,用来描述state发生了什么变更。

import {
    INCREMENT,
    DECREMENT
} from "./action-types";

export function increment(number) {
    return{
        type: INCREMENT,
        number
    }
}

export function decrement(number) {
    return{
        type: DECREMENT,
        number
    }
}

假设在计数器组件Calculate中我们知道react-redux中connect函数的基本用法是:

const mapStateToProps = state => ({
	count: state.count
})

const mapActionToDispatch = dispatch => ({
    Increment(number){
        dispatch(xxx)
    },
    Decrement(number){
        dispatch(xxx)
    }
})
export default connect(mapStateToProps, mapActionToDispatch)(Calculate);

​ 由用法我们知道connect函数第一个和第二个参数都是函数,函数的返回值是一个对象,而connect函数的返回值是一个高阶组件,所以才能进行调用( 高阶组件是参数为组件,返回值为新组件的函数),而mapStateToProps中的state参数以及mapActionToDispatch中的dispatch参数从何而来呢?我们看一下自己写的connect函数:

import React from 'react'
import store from "./index";

function connect(mapStateToProps, mapActionToDispatch) {
    return function (WrapComponent) { // connect函数返回值是高阶组件
        return class extends React.Component{ // 高阶组件返回值是一个新的组件
            constructor(props) {
                super(props);
                this.state = {
                	// store.getState() 获取state对象
                    storeState: mapStateToProps(store.getState())
                }
            }

            componentDidMount() {
            	// 进行监听 一旦state中的属性值发生变化就调用setState来重新渲染
                this.subscribe = store.subscribe(() => {
                    this.setState({
                        storeState: mapStateToProps(store.getState())
                    })
                })
            }

            componentWillUnmount() {
            	// 取消监听
                this.subscribe()
            }

            render() {
                return(
                    
                )
            }
        }
    }
}

export default connect

其中store.getState()就是获取state对象,store.dispatch就是用于派发action

其中

{…mapStateToProps(store.getState())}
{…mapActionToDispatch(store.dispatch)}/>

就是将props以及statedispatch传递给高阶函数所返回的新组件,所以才能用props.increment()函数以及props.count属性。

在写完connect函数之后我们用一下试一试:

import React from 'react'
import connect from ".././store/connect";
import {
    increment,
    decrement
} from ".././store/actions";

function Calculate(props) {
    const {count} = props
    return(
        
{count}
) } const mapStateToProps = state => ({ count: state.count } ) const mapActionToProps = dispatch => ({ Increment(number){ dispatch(increment(number)) }, Decrement(number){ dispatch(decrement(number)) } }) export default connect(mapStateToProps, mapActionToProps)(Calculate);

测试的结果也是没有问题的,以上就是我对在redux中手动实现connect函数的基本理解。

你可能感兴趣的:(react学习,react,前端)