react与redux通信之hook

38次阅读

共计 2104 个字符,预计需要花费 6 分钟才能阅读完成。

react 和 redux 建立通信的方式

有 2 种方案:

  • 老方案 connect
  • 新方案 hook

老方案 connect

曾经,我们会使用 connect 建立 react 和 redux 的通信,例如,在一个 class 写法的组件中:

import React from 'react'
import {bindActionCreators} from 'redux'
import {connect} from 'react-redux'
import globalAction from 'actions/global'
@connect(
    // 取得 reducer 中的 state
    state => ({global: state.global}), 
    // 取得 action
    dispatch => bindActionCreators({globalAction}, dispatch)
)
class Component extends React.Component {componentDidMount() {
        // 从 props 中读取 reducer 和 action
        const {global, globalAction} = this.props
        globalAction()
        console.log(global)
    }
    render() {return <div />}
}

对于用习惯了 class 组件的开发者来说,这种写法烂熟于心了。但是,不管你多喜欢这种模式,还是得学习 react hook。

新方案 hook

随着 react16.8 的发布,hook 功能正式投入使用。
将 react 的 class 组件转换成函数式组件,想必你已经看过官网的 demo 了,如果没看,回头看一下也不晚。那么,如果我们使用了 hook,又该如何跟 redux 通信呢?
针对于这个问题,业界有人提供了一个取代 react-redux 的新插件 redux-react-hook。
redux-react-hook 使用了 react 提供的 Context(上下文)功能,给顶层组件 Provide 传入了 store 对象,绑定到上下文。
使用了 redux-react-hook 之后,上面的 demo 就变成了下面这种写法:

import React, {useEffect} from 'react'
import {useDispatch, useMappedState, StoreContext} from 'redux-react-hook'
import globalAction from 'actions/global'
function Component {
    // 获取上下文的 store 对象
    const store = useContext(StoreContext)
    // 从 store 中读取 reducer
    const {global} = store
    // 从 store 中读取 dispatch
    const dispatch = useDispatch()
        
    useEffect(() => {dispatch(globalAction())
        console.log(global)
    }, [global, dispatch, globalAction])
    
    render() {return <div />}
}

修改后的 demo 使用到了 redux-react-hook 提供的其中 2 个 API,StoreContext 和 useDispatch,其次,还可以使用 useMappedState 来获取 reducer 中的状态。

const mapState = useCallback(
    state => ({global: state.global}),
    [],);
const {global} = useMappedState(mapState);

redux-react-hook

简单介绍写 3 个 API,StoreContext,useDispatch,useMappedState。

StoreContext

React 提供的 createContext 创建上下文,返回该对象。

import {createContext} from 'react';
// 创建 context
const StoreContext = createContext<TStore | null>(null)
return StoreContext

useDispatch

读取 StoreContext,返回 dispatch。

function useDispatch(): Dispatch<TAction> {
    // 从上下文读取 store
    const store = useContext(StoreContext);
    if (!store) {
      // store 不存在,抛出异常
      throw new MissingProviderError();}
    return store.dispatch;
  }
return useDispatch

useMappedState

useMappedState 跟其他 2 个 API 不太一样,它是一个自定义的 hook,用来订阅 reducer 里的状态。

总结

hook 式的写法究竟是好是坏,暂且无法分辨,就像有人觉得函数式编程很好,但有人觉得函数式编程使得代码难于维护。
可以预见的是,当你使用了 hook,会在项目中逐渐把 class 消灭,最后跟 class 语法糖告别,回归函数的世界。

正文完
 0