reactjsreact-context

Why App component is not getting context update


I'm trying to set up a context from a custom hook. Here's my code:

usePlayerInterface.jsx

import { useState } from 'react';

export function usePlayerInterface() {
  const [userAction, setUserAction] = useState(false);
  // ...code that calls setUserAction from a user generated event
}

PlayerInterfaceContext.jsx

import { createContext } from 'react';

const PlayerInterfaceContext = createContext({
  userAction: false
});

export default PlayerInterfaceContext;

StandardExerciseContainer.jsx

import { usePlayerInterface } from '../hooks/usePlayerInterface';
import { useEffect } from 'react';
import PlayerInterfaceContext from '../context/PlayerInterfaceContext';

const StandardExerciseContainer = ({
  children
}) => {
  const { userAction } = usePlayerInterface();
  
  useEffect(() => {
    // THIS GETS CALLED AS EXPECTED
    console.log('userAction in container:', userAction);
  }, [userAction]);

  return (
    <PlayerInterfaceContext.Provider value={{ userAction }}>
      {children}
    </PlayerInterfaceContext.Provider>
  )
}

export default StandardExerciseContainer;

App.jsx

import { useEffect, useContext } from 'react';
import StandardExerciseContainer from '@common/react/components/StandardExerciseContainer.jsx';
import PlayerInterfaceContext from '../context/PlayerInterfaceContext';

const App = () => {
  const { userAction } = useContext(PlayerInterfaceContext);

  useEffect(() => {
    // THIS IS ONLY CALLED FOR THE INITIAL VALUE
    console.log('userAction in app:', userAction);
  }, [userAction]);

  return (
    <StandardExerciseContainer>
      // ...child components
    </StandardExerciseContainer>
  )
}

Logs are

  on page load:
    userAction in container: false
    userAction in app: false
  on user event
    userAction in container: true

App never gets the updated value. Can't for the life of me figure out what I'm doing wrong.


Solution

  • If you want to use the context value on your children component, you need to wrap your child ren component using your provider in your case :

    <StandardExerciseContainer>
      //Children component
    </StandardExerciseContainer>
    

    The code above is not enough to give a clear answer.

    If your App component is not getting context updates, the most common reason is that it's not wrapped inside the corresponding Context Provider.

    Make sure you wrap your App (or any component that needs to consume context) with your Provider component, like this:

    import { MyContextProvider } from './MyContext';
    
    const Root = () => (
      <MyContextProvider>
        <App />
      </MyContextProvider>
    );