react-redux的使用与源码

124 阅读2分钟

react-redux作用

如果只使用redux与react会麻烦很多,首先每个组件的store要靠上下文来传递

//一个js文件模块中创造context上下文实例
import React from 'react'
let context=React.createContext()
export default context
//祖先组件中设置值
import React from 'react'
import store from '...'
import context from '...'

function Father(){
    return <context.Provider value={{store:store}}>
        ...
    </context.Provider>
}

```js
//后代组件
import context from '...'
class Son extends React.component{
    static contextType=context
    render(){
        let {}=this.context
        return <>
        
        </>
    }
}

之后就是每个用到store中state的组件都会在componentDidMount这个生命周期函数中store.subscribe(()=>{this.forceUnpdate())向事件池中添加方法

react-redux的使用

而使用react-redux会方便,通过react-redux中的Provider组件传递store值,在其他后代组件中使用connect方法

//在祖先组件中
import store from '...'
import {Provider} from "react-redux"

function App(){
    return <Provider store={store}>
        ...
    </Provider>
}

import {connect} from "react-redux"
class Son extends React.components{
    render(){
        let {}=this.props
    }
}
//这里的第二个参数可以是函数也可以是对象,如果是对象会把它转化成函数,函数返回一个对象,对象的属性名就是属性值对应的方法名
export default connect(state=>{xxx:state.xxx.yyy},dispatch=>{})(Son)

react-redux的源码

//一个js文件模块中创造context上下文实例
import React from 'react'
let context=React.createContext()
export default context

Provider组件的使用,导入后在组件中传入store属性,在标签内部有子代元素,在定义Provider组件,要拿到store和children属性,渲染的元素是上下文组件,为所有子代组件添加了store上下文

import context from '...'
class Provider extends React.Component{
    render(){
        let {store,children}=this.props
        return <context.Provider value={{store}}>
            {children}
        </context.Provider>
    }
}

function connect(stateFunc,dispatchFunc){
    if(stateFunc===undefined){
        stateFunc=state=>{
            return {}
        }
    }
    if(dispatch===undefined){
        dispatchFunc=dispatch=>{
            return {}
        }
    }
    if(dispatchFunc!=null&&typeof dispatchFunc==="object"){
        let oldObj=dispatchFunc   
        dispatchFunc=dispatch=>{
            let obj={}
            Object.keys(oldObj).forEach(key=>{
                obj[key]=(...args)=>{
                    dispatch(oldObj[key](...args))
                }
            })
            return obj
        }
    }
    return function get(Component){
        return class Proxy extends React.Component{
            static contextType=context
            render(){
                let {store}=this.context
                let stateObj=stateFunc(store.getState())
                let dispatchObj=stateFunc(store.dispatch)
                let result={
                    ...this.props,
                    ...stateObj,
                    ...dispatchObj
                }
                return <Component {...result}></Component>
            }
            componentDisMount(){
                let {store}=this.context
                store.subscribe(()=>{
                    this.forceUpdate()
                })
            }
        }
    }
}

export Provider
export connect

总结

react-redux的实现就是两个组件,一个是Provider组件,渲染了一个上下文组件,把传入Provider组件的store属性放到上下文的value上,并把Provider的子元素显示,这样后代中都可以得到这个store了,在后代组件中(可以得到store的组件),导入connect并调用它传入两个方法(第二个可以是个对象)这样又返回一个方法调用后传入当前的组件返回值是一个新的组件,这里用到了科里化函数先把connect传入的两个实参进行处理,如果没有传入要自己手动写一个函数返回空对象,要是第二个参数是对象就把它写成方法,方法返回一个对象,对象的key就是原来对象的key对应的值是一个函数,函数中执行dispatch(调用原来的value函数)