React with Context, reduce dispatch boilerplate

390 views Asked by At

I was looking for a way to reduce the boilerplate when using React context. Normally, when dispatching actions, I do this:

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

So I tried this (outside and inside of the component):

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

And tried to call it like this:

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

That, of course, didn't work. I got the following error:

React Hook "useDispatch" is called in function "toggleLoading" which is neither a React function component or a custom React Hook function react-hooks/rules-of-hooks

So I tried to call it within the component:

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

And I get the following error:

React Hook "useDispatch" is called conditionally. React Hooks must be called in the exact same order in every component render react-hooks/rules-of-hooks

Any ideas?

1

There are 1 answers

2
Douglas Gardim On BEST ANSWER

Your useDispatch function is not a "hook", so you shouldn't name it with the "use" prefix.

A more usual approach for what you are trying to achieve would be:

1- Create an actionCreator function:

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

2- Dispatch using your actionCreator function:

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