Home

CV

Blog

Brand

Working around the React context default value with TypeScript.

Liam Hales

Liam Hales

Senior Software Engineer

TypeScript

React

November 2021 - 3 years ago

Introduction.

When using
React
context you are required to provide a
defaultValue
argument to
createContext
. This is for when the context is used outside the corresponding
Provider
.
The
defaultValue
argument makes sense for some cases such as unit testing components in isolation without wrapping them. However I think it should be an optional argument as it seems cumbersome to add this default value if you know you are only going to be using the context within the corresponding
Provider
.
 

The problem.

For JavaScript this may not seem like an issue as you can simply provide an empty object or
undefined
as the default value and by the time you use the context the value will have been populated by the
Provider
anyway completely overwriting the default value.
However for TypeScript, an empty object leads to all sorts of type errors conflicting with the actual context value type and if you provide
undefined
destructuring the context value when using
useContext
isn't possible until you have type checked the value.
 

The solution.

The solution is to set the
defaultValue
argument to
undefined
when calling
createContext
. Remember to correctly type the context value.
const context = createContext<IContext | undefined>(undefined);
Then create a simple hook which uses
useContext
and type checks the value before returning it. If the value is indeed
undefined
it throws an error and assumes that the hook is being used outside the corresponding
Provider
.
const useCustomContext<T extends Record<string, unknown>>(
  context: Context<T | undefined>
): T {

  // Get the context value which could be undefined
  const value = useContext(context);

  // Check the value is not undefined and
  // has been initialised by the provider
  if (value == null) {
    throw new Error(
      'The "useContext" hook must be used within the corresponding context "Provider"'
    );
  }

  return value;
}
This solves the issue, uses strict typing and will
throw
the custom
Error
if the hook is accidentally used outside the corresponding
Provider
which can help with debugging. All you need to do now is use it!
const { value ... } = useCustomContext(context);
 

Summary.

As we have seen this works well for
React
context, but you can use this logic for any hook where you need to unwrap state or data of some sort that could be
undefined
. Just make sure you use it where you know the value will be defined otherwise your custom
Error
will get thrown. Try it yourself!

Get in touch

Thank you for stopping by! Please feel free to contact me with any questions you may have, I’ll try my best to get back to you.

2024 - Liam Hales

Designed & Built by Liam Hales