Custom context hooks in react
May 04, 2020
I use contexts a decent amount in react, and I typically write custom hooks for them. The hooks are largely boilerplate, taking the form of:
- useContext
- check the value
- return the value or throw an Error.
I released react-instant-hook to remove all of that boilerplate and to make custom hooks more convenient. It’s pretty simple (less than 40 lines) and allows you to make custom hooks for your contexts with a single function call.
I got the idea for this library while reading ‘How to use React context effectively’ by Kent C. Dodds. It’s a great read on context best practices.
This post isn’t going to go explain contexts, or when to use them, I think Kent’s post sums that up really well. This will simply serve as a brief introduction to the module and how to use it.
Using react-instant-hook
Taking the example from Kent’s blog post…
/*** Adapted from* https://kentcdodds.com/blog/how-to-use-react-context-effectively**/import React from 'react';import { getHook } from 'react-instant-hook';const CountStateContext = React.createContext();const CountDispatchContext = React.createContext();function countReducer(state, action) { ... }function CountProvider({children}) {const [state, dispatch] = React.useReducer(countReducer, {count: 0})return (<CountStateContext.Provider value={state}><CountDispatchContext.Provider value={dispatch}>{children}</CountDispatchContext.Provider></CountStateContext.Provider>)}
We establish two contexts, a reducer and a provider component.
Using react-instant-hook
, we can create the custom hooks for our contexts in just 3 lines!
const useCountState = getHook(CountStateContext);const useCountDispatch = getHook(CountDispatchContext);const useCount = getHook([CountStateContext,CountDispatchContext]);
As an aside, I really like this pattern of isolating the concerns of your contexts. Less unused variables, and clearer code - it’s a win-win! 🚀
For the most part the module is unopinionated, with the exception of validating the value returned by the context. You shouldn’t be using hooks outside of their corresponding providers, so it’s better that the hooks fail fast than fail silently.
By default, react-instant-hook
validates that the value returned from the context is not undefined. This can be overwritten with an optional secondary parameter.
// Default validation - let's just make sure the value isn't undefinedconst validateValue = (value) => value !== undefined;
If this validation fails, react-instant-hook
will throw an error. If you want to go rogue and use your hook without any validation, pass () => true
as the second parameter.
Not pretty, but neither is using a context consumer outside of the provider!
If you have any questions or suggestions, you can tweet me or leave an issue in the github repo.