If you’re a React developer using React Contexts, then there will no doubt be times when you try to retrieve a context that you’ve created, only for it to be undefined.

A common pattern you’ll see is this:

import {createContext, useContext} from 'react';

const ExampleContext = createContext(null);

/**
 * A Provider to wrap around your components
 */
export const ExampleProvider = ({children, startValue}) => {
    const [exampleValue, setExampleValue] = useState(startValue);

    useEffect(() => {
        //
        // Some code to initialize the exampleValue
        //
        setExampleValue(initializedValue);
    },[])

    return (
        <ExampleContext.Provider value={exampleValue}>
            {children}
        </ExampleContext.Provider>
    );
}

/**
 * A hook to get the current context value
 */
export const useExample = () => {
    const exampleValue = useContext(ExampleContext);
    if(exampleValue === undefined) {
        throw new Error('useExample returned undefined. Are you sure you component is inside an Example Provider?')
    }
    return exampleValue;
}

If you search online for “React useContext returns undefined”, you will generally be directed to ensure that the component calling useExample is a descendant of the ExampleProvider. However, this is not the only possibility.

Take note that the default value for our ExampleContext is null, not undefined. Therefore, exampleValue has been updated.

During your debugging, you decide to call console.log({initializedValue}) inside your useEffect, but you see that it’s definitely defined just before you call setExampleValue.

What might be happening is what happened to me. I was creating an IntercomProvider for a React app so that components could make calls to Intercom. I was loading Intercom into my app, just fine, but useIntercom kept returning undefined.

I finally realized that the issue was a little wrinkle with my state-setter and the fact that Intercom is a function.

The setter returned by useState has two signatures. The first takes a value and just updates the state to that value. The second takes a function which takes the current state as a parameter and returns the new state.

This all works cleanly unless your state value also happens to be a function.

When I did this:

setIntercom(intercom);

React saw that I was passing in a function and so called it and set the state to the return value of that function. The Intercom functions happens to be a void returning function, hence the undefined value.

Instead, I now do:

setIntercom(() => intercom);

Everything now works as it should.

If you find yourself in a similar position, it’s probably a good idea to throw a quick comment to explain why you’re using the function form, so that someone doesn’t come and “clean it up” later.