title: React Context: Error: userState must be used within a UserProvider despite nested in Provider?
body: <p>I am following this great <a href="https://kentcdodds.com/blog/how-to-use-react-context-effectively" rel="nofollow noreferrer">tut</a> by Kent C. Dodds regarding usage React Context.</p>
  <p>But I actually have this component nested within the provider so not sure why I am getting.</p>
  <blockquote>
  <p>Error: userState must be used within a UserProvider</p>
  </blockquote>
  <p>So perhaps I am not getting the point of creating a function which is throwing an Error despite following how you should use the provider... Perhaps I implemented it incorrectly?</p>
  <p>So this is my userContext setup:</p>
  <pre><code>import React, { useState, useEffect, useContext, useReducer } from 'react';
  
  var initialState = {
   ...state...
  };
  
  var UserStateContext = React.createContext();
  var UserContextDispatch = React.createContext();
  
  function setLocalStorage(key, value) {
     ...function innards...
  }
  
  function getLocalStorage(key, initialValue) {
     ...function innards...
  }
  
  function UserProvider({ children }) {
    function userReducer(state, { type, payload }) {    
      switch (type) {
        case 'setUserId': {
          return { ...state, ...{ id: payload.id } };
        }
  
        case 'setAvatar': {
          return {
            ...state,
            ...{ avatar: payload.avatar }
          };
        }
  
        case 'setIsRoutingVisible': {
          return {
            ...state,
            ...{ isRoutingVisible: payload.isRoutingVisible }
          };
        }
  
        case 'addMarker': {
          user.isLengthOfMarkersLessThanTwo
            ? {
                ...state,
                markers: user.markers.concat(payload.marker)
              }
            : null;
          break;
        }
      
        case 'setMap': {
          return {
            ...state,
            currentMap: payload.curerntMap
          };
        }
  
        default: {
          throw new Error(`Unhandled action type: ${type}`);
        }
      }
    }
  
    const [user, setUser] = useState(() =&gt; getLocalStorage('user', initialState));
  
    var [state, dispatch] = useReducer(userReducer, user);
  
    useEffect(() =&gt; {
      setLocalStorage('user', state);
    }, [state]);
  
    return (
      &lt;UserStateContext.Provider value={state}&gt;
        &lt;UserContextDispatch.Provider value={dispatch}&gt;
          {children}
        &lt;/UserContextDispatch.Provider&gt;
      &lt;/UserStateContext.Provider&gt;
    );
  }
  
  function userState() {
    const context = React.useContext(UserStateContext);
    if (context === undefined) {
      throw new Error('userState must be used within a UserProvider');
    }
    return context;
  }
  
  function userDispatch() {
    const context = React.useContext(UserContextDispatch);
    if (context === undefined) {
      throw new Error('userDispatch must be used within a UserProvider');
    }
    return context;
  }
  
  export { UserProvider, userState, userDispatch };
  </code></pre>
  <p>The error is pointing to my Map component, which is passing <code>state</code> and <code>dispatch</code> props from <code>UserContext</code> to my Routing component which is a class component.</p>
  <pre><code>import React, { useState, useContext, useEffect, useRef, useCallback } from 'react';
  import { Button } from 'semantic-ui-react';
  
  import L from 'leaflet';
  import * as ELG from 'esri-leaflet-geocoder';
  import { Map } from 'react-leaflet';
  import { Dimmer, Loader } from 'semantic-ui-react';
  
  import Routing from '../RoutingMachine/RoutingMachine.jsx';
  import { userState, userDispatch } from '../Context/UserContext.jsx';
  
  import UIContext from '../Context/UIContext.jsx';
  
  import { stringify } from 'flatted';
  
  export default function MyMap({}) {
    var [zoom, setZoom] = useState(18);
    var [animate, setAnimate] = useState(false);
    var [userLocation, setUserLocation] = useState(null);
  
    var mapRef = useRef();
  
    console.log('userState() ', userState());
    var {
      avatar,
      currentMap,
      id,
      isLengthOfMarkersLessThanTwo,
      isRoutingVisible,
      markers,
      removeRoutingMachine
    } = userState();
  
    var dispatch = userDispatch();
  
    var { isMobile, isDesktop } = useContext(UIContext);
  
    useEffect(() =&gt; {
      if (isRoutingVisible === false) {
        dispatch({
          type: 'setIsRoutingVisible',
          payload: {
            isRoutingVisible: true
          }
        });
      }
    });
  
    useEffect(() =&gt; {
      if (markers.length === 2) {
        dispatch({
          type: 'isLengthOfMarkersLessThanTwoFalse',
          payload: { isLengthOfMarkersLessThanTwo: false }
        });
      }
    }, [JSON.stringify(markers)]);
  
    return (
      &lt;Map
        animate={animate}
        onLocationFound={handleOnLocationFound}
        zoom={zoom}
        ref={mapRef}
      &gt;
         
        {isRoutingVisible &amp;&amp; (
          &lt;Routing
            markers={markers}
            dispatch={dispatch}
            removeRoutingMachine={removeRoutingMachine}
            map={currentMap}
            userLocation={userLocation}
            isMobile={isMobile}
            isDesktop={isDesktop}
          /&gt;
        )}
      &lt;/Map&gt;
    );
  }
  </code></pre>