Configure thunk action creators and redux dev-tools with React’s use Reducer hook.

Updated on 8 May 193 min read

Redux development

When does someone choose to put a state in redux?

  1. To avoid props drilling.
  2. To use the redux state as a cache between mount/unmount.
  3. To avoid refactoring at a later stage when a new component asks for the same state.
  4. Some folks dislike the idea to keep API calls inside the component.
  5. Awesome debugging tool. At least here you can time travel.

There could be more than 5 points, but these are the ones I found most essential.

No spoilers ahead :D

BUT, when you don’t need 1, 2 and 3 it creates a very small and familiar problem.

My favorite one:

Why are the filters not resetting when I move out of the screen.
componentWillUnmount() {
dispatch({type: "RESET"});
}

What if we can keep the state in component and still get 3, 4 and 5. :D

Solving 4 will automatically solve 3 as long as you are using React redux thunk.

First, let’s get the 4th i.e. Async actions.

1. Creating a custom React useReducer hook.

import { useReducer } from 'react'function useReducerWithThunk(reducer, initialState) {
const[state, dispatch]=useReducer(reducer,initialState);letcustomDispatch=(action)=>{
if (typeofaction==='function') {
action(customDispatch);
} else {
dispatch(action);
}
};return [state, customDispatch];
}

2. Using the above useReducer hook.

import useReducerWithThunk from "./useReducerWithThunk";// Async action creator
const fetchData = () => async (dispatch) => {
dispatch({ type:"FETCH" });
}export default function App() {
const[count, dispatch]=useReducerWithThunk(reducer,0);

function fetchData() {
dispatch(fetchData());
}

return <button onClick={fetchData}>Get Data!</button>
}

Done, that’s all you need to dispatch a function instead of an object. :D

Now, let’s knock down the 5th i.e Awesome Redux Devtools support.

Before that, we need to consider the below points.

  • Devtools should support redux’s store along with React userReducer’s.
  • The useReducer is completely isolated and we can’t combine them to create a rootReducer which is what we are trying to avoid.
  • But, we can create a separate store for each useReducer in dev-tools and switch between them using the dropdown below.
Select instances

Implementation:

Devtools will only initialize if the name parameter is passed. See below.

Usage:

The above useReducer — React redux hook can be used as below.

const[count, dispatch]= useReducerWithThunk(reducer,0, name // optional);

Result:

Here, a separate instance is created which can be switched using the dropdown.

Fully functional redux dev tools using useReducer

End Notes:

It would be much better if only a few complicated reducers are connected to Redux devtools or else the overhead involved in switching and finding the appropriate instance will exceed the benefits.

But at least the reason of not able to use devtools should not prevent you from keeping the state local.

Thanks for taking the time to read this, I hope you find it useful.

[@portabletext/react] Unknown block type "urllink", specify a component for it in the `components.types` prop

Reference:

[@portabletext/react] Unknown block type "urllink", specify a component for it in the `components.types` prop
[@portabletext/react] Unknown block type "urllink", specify a component for it in the `components.types` prop