The useContext hook is not a function error means that React is trying to call useContext as if it were a function, but it’s not finding it where it expects to. This almost always boils down to a version mismatch or an incorrect import.

Here are the common causes and their fixes:

  1. Incorrect React Version: useContext was introduced in React 16.3. If you’re using an older version of React, it simply won’t exist.

    • Diagnosis: Check your package.json file for the react and react-dom dependencies.
    • Fix: Ensure both react and react-dom are at version 16.3.0 or higher. For example, update them to the latest stable versions:
      npm install react@latest react-dom@latest
      # or
      yarn add react@latest react-dom@latest
      
    • Why it works: This provides the useContext API that React expects.
  2. Incorrect Import: You might be importing useContext from the wrong place. It should always be imported directly from the react package.

    • Diagnosis: Search your codebase for useContext imports. Look for patterns like import { useContext } from 'some-other-library'; or import useContext from 'react';.
    • Fix: Ensure your imports look like this:
      import React, { useContext } from 'react';
      // or if you are using named exports in your own modules:
      // import { useContext } from './my-context-provider'; // This is WRONG for the hook itself
      
      The correct import for the hook is always:
      import { useContext } from 'react';
      
    • Why it works: This tells JavaScript to get the useContext function from the official React library, where it’s defined.
  3. Multiple React Versions in Dependencies: Sometimes, even if your top-level package.json specifies a correct React version, a dependency might be pulling in an older version of React. This can lead to the useContext function being unavailable or the wrong version being used.

    • Diagnosis: Run npm ls react or yarn why react in your project’s root directory. This will show you where React is being installed from. Look for multiple versions.
    • Fix: Use npm dedupe or yarn dedupe to try and resolve version conflicts. If that doesn’t work, you might need to explicitly resolutions in package.json (for Yarn) or overrides (for npm) to force a specific version:
      // package.json (npm example)
      "overrides": {
        "react": "^18.0.0",
        "react-dom": "^18.0.0"
      }
      
      Then run npm install or yarn install.
    • Why it works: This ensures that only one, compatible version of React is installed and used throughout your application, preventing conflicting useContext implementations.
  4. Using useContext in a Class Component: The useContext hook is exclusively for functional components. You cannot use it within a class component’s lifecycle methods or render method.

    • Diagnosis: Review the component where you’re seeing the useContext error. If it’s a class component (defined using the class keyword), this is the problem.
    • Fix: Convert the class component to a functional component, or use the Consumer component of your context if you must remain with class components.
      • Functional Component Conversion:
        // Before (Class Component)
        // import React, { Component, createContext } from 'react';
        // const MyContext = createContext();
        // class MyComponent extends Component {
        //   render() {
        //     return (
        //       <MyContext.Consumer>
        //         {value => <div>{value}</div>}
        //       </MyContext.Consumer>
        //     );
        //   }
        // }
        
        // After (Functional Component)
        import React, { useContext } from 'react';
        const MyContext = React.createContext(); // Or wherever your context is defined
        
        function MyComponent() {
          const value = useContext(MyContext);
          return <div>{value}</div>;
        }
        
    • Why it works: Hooks like useContext are designed to be called at the top level of functional components, leveraging JavaScript closures and React’s internal state management for functional components.
  5. Missing Context Provider: While this usually results in a different error (e.g., undefined context value), in some complex setups or with custom build tools, it might manifest as a useContext issue if the provider isn’t correctly integrated or if the context object itself is malformed before being passed to useContext.

    • Diagnosis: Trace the usage of your Context.Provider component. Ensure it wraps the component calling useContext.
    • Fix: Make sure you have a MyContext.Provider value={...}> wrapping the component that calls useContext(MyContext).
      // Parent component
      function App() {
        return (
          <MyContext.Provider value="someValue">
            <MyComponent />
          </MyContext.Provider>
        );
      }
      
      // MyComponent.js
      import React, { useContext } from 'react';
      // Assume MyContext is imported correctly from where it's defined
      function MyComponent() {
        const value = useContext(MyContext); // This will now work
        return <div>{value}</div>;
      }
      
    • Why it works: useContext relies on React’s internal context system to find the nearest Provider ancestor. Without a provider, there’s no value to return, and in certain edge cases, this can lead to the hook being called in an invalid state.
  6. Bundler/Transpiler Configuration Issues: Less common, but your build tools (like Webpack, Babel, or Vite) might be misconfigured, preventing useContext from being correctly transpiled or bundled.

    • Diagnosis: Check your Babel configuration (.babelrc, babel.config.js) and Webpack configuration (webpack.config.js). Ensure you have presets and plugins that support modern React features (like @babel/preset-react).
    • Fix: Update your Babel presets to include @babel/preset-react and ensure it’s configured to target your React version. For example, in .babelrc:
      {
        "presets": [
          "@babel/preset-env",
          ["@babel/preset-react", { "runtime": "automatic" }] // or "classic" if you prefer
        ]
      }
      
      Run npm install @babel/preset-react --save-dev if it’s not already installed.
    • Why it works: The transpiler needs to understand how to convert JSX and modern JavaScript syntax, including hooks, into code that browsers can execute.

The next error you’ll likely encounter if you’ve fixed the useContext problem but your context is still not being provided correctly is that useContext will return undefined or the default value you might have set, leading to errors when you try to use that undefined value.

Want structured learning?

Take the full React course →