【问题标题】:React with Context, reduce dispatch boilerplate与上下文反应,减少调度样板
【发布时间】:2021-01-16 22:08:00
【问题描述】:

我一直在寻找一种在使用 React 上下文时减少样板的方法。通常,在调度操作时,我会这样做:

    applicationDispatch({
      type: applicationActionTypes.setIsLoading,
      payload: !isLoading,
    });

所以我尝试了这个(在 组件内部):

const useDispatch = (dispatch, method, payload) =>
  dispatch({
    type: applicationActionTypes[method],
    payload: payload,
  });

并试图这样称呼它:

function App(){
const {application, applicationDispatch} = React.useContext(ApplicationStore)
const {isLoading} = application
const toggleLoading = ()=>useDipatch(applicationDispatch, applicationActionTypes.setIsLoading, payload)
...
}

那当然没有用。我收到以下错误:

React Hook "useDispatch" 在函数 "toggleLoading" 中被调用,该函数既不是 React 函数组件也不是自定义 React Hook 函数 react-hooks/rules-of-hooks

所以我尝试在组件中调用它:

return (
<div>
   {someBool && <Modal
          onClick={useDispatch(applicationDispatch, setIsLoading, !isLoading)}>
      ...
      </Modal>}
</div>
}

我收到以下错误:

有条件地调用 React Hook "useDispatch"。在每个组件渲染 react-hooks/rules-of-hooks 中,必须以完全相同的顺序调用 React Hooks

有什么想法吗?

【问题讨论】:

    标签: reactjs react-hooks react-context


    【解决方案1】:

    你的useDispatch 函数不是一个“钩子”,所以你不应该用“use”前缀来命名它。

    对于您要实现的目标,更常用的方法是:

    1- 创建一个actionCreator函数:

    function runAction(method, payload) {
      return {
        type: applicationActionTypes[method],
        payload: payload,
      }
    }
    

    2- 使用您的 actionCreator 函数进行调度:

    return (
    <div>
       {someBool && <Modal
              onClick={()=>applicationDispatch(runAction("setIsLoading", !isLoading))}>
          ...
          </Modal>}
    </div>
    }
    

    【讨论】:

    • 谢谢!我喜欢那个实现。所以函数名的“use...”部分是在暗示它是一个钩子?还有什么其他东西表明它是一个钩子吗?
    • 是的,唯一的信号是“使用”前缀。挂钩是非常特殊的功能,因此他们创建了这个由 lint 工具强制执行的约定。当您真的打算使用或创建钩子函数时非常有用。显然,约定对于人们轻松识别函数是钩子也是必不可少的。