How to Use React Hooks Inside Class Components

Working with React for more than a decade has given me plenty of chances to experiment with both class components and functional components.

When Hooks were introduced, I immediately loved how simple they made state management and side effects. But in real-world projects, I often had to deal with older codebases full of class components.

Rewriting everything into functional components wasn’t always an option. So, I had to find ways to bring the power of Hooks into class components.

In this tutorial, I’ll show you exactly how I do that. I’ll cover different methods, share full code examples, and explain each step in simple terms.

Why Hooks Don’t Work Directly in Class Components

Hooks are designed to work only inside functional components. That’s part of the React design philosophy.

If you try to call something like useState or useEffect inside a class component, React will throw an error. But that doesn’t mean you can’t use hook logic in class-based projects. You just need some workarounds.

Method 1 – Wrap Hooks in a Higher-Order Component (HOC)

One of the easiest ways I’ve used is to create a Higher-Order Component (HOC) that uses Hooks internally and passes the data down as props.

Here’s the complete code:

import React, { useState, useEffect } from "react";

// HOC that injects hook values into a class component
function withWindowWidth(WrappedComponent) {
  return function Wrapper(props) {
    const [width, setWidth] = useState(window.innerWidth);

    useEffect(() => {
      const handleResize = () => setWidth(window.innerWidth);
      window.addEventListener("resize", handleResize);
      return () => window.removeEventListener("resize", handleResize);
    }, []);

    return <WrappedComponent {...props} windowWidth={width} />;
  };
}

// Class component that receives window width via props
class Dashboard extends React.Component {
  render() {
    return (
      <div>
        <h2>Current Window Width: {this.props.windowWidth}px</h2>
      </div>
    );
  }
}

export default withWindowWidth(Dashboard);

You can refer to the screenshot below to see the output.

Use React Hooks Inside Class Components

In this example, the HOC uses useState and useEffect to track window size. The class component (Dashboard) doesn’t use Hooks directly but still benefits from them through props.

Method 2 – Use a Custom Hook with a Wrapper Function

Sometimes, I want to reuse a custom Hook I already wrote. In that case, I wrap it in a small functional component and render it inside my class component.

Here’s how:

import React from "react";

// Custom Hook
function useOnlineStatus() {
  const [isOnline, setIsOnline] = React.useState(navigator.onLine);

  React.useEffect(() => {
    const handleOnline = () => setIsOnline(true);
    const handleOffline = () => setIsOnline(false);

    window.addEventListener("online", handleOnline);
    window.addEventListener("offline", handleOffline);

    return () => {
      window.removeEventListener("online", handleOnline);
      window.removeEventListener("offline", handleOffline);
    };
  }, []);

  return isOnline;
}

// Functional wrapper
function OnlineStatusWrapper({ onChange }) {
  const status = useOnlineStatus();
  React.useEffect(() => {
    onChange(status);
  }, [status, onChange]);
  return null;
}

// Class component
class App extends React.Component {
  state = { online: navigator.onLine };

  handleStatusChange = (status) => {
    this.setState({ online: status });
  };

  render() {
    return (
      <div>
        <h2>User is {this.state.online ? "Online" : "Offline"}</h2>
        <OnlineStatusWrapper onChange={this.handleStatusChange} />
      </div>
    );
  }
}

export default App;

You can refer to the screenshot below to see the output.

Use Hooks Inside Class Components in React

The Hook useOnlineStatus tracks whether the user is online or offline. The wrapper component sends the Hook’s value back to the class component using a callback.

Method 3 – Use Context API with Hooks

Another approach I’ve found useful is combining Hooks with React Context.

Here’s a full working example:

import React, { useState, useEffect, createContext, useContext } from "react";

// Create Context
const LocationContext = createContext();

// Provider using Hooks
function LocationProvider({ children }) {
  const [location, setLocation] = useState("New York");

  useEffect(() => {
    const timer = setTimeout(() => {
      setLocation("San Francisco");
    }, 5000);

    return () => clearTimeout(timer);
  }, []);

  return (
    <LocationContext.Provider value={location}>
      {children}
    </LocationContext.Provider>
  );
}

// Hook for consuming context
function useLocation() {
  return useContext(LocationContext);
}

// Class component consuming context
class Profile extends React.Component {
  static contextType = LocationContext;

  render() {
    return <h2>User Location: {this.context}</h2>;
  }
}

// App
function App() {
  return (
    <LocationProvider>
      <Profile />
    </LocationProvider>
  );
}

export default App;

You can refer to the screenshot below to see the output.

React Hooks Inside Class Components

The LocationProvider uses Hooks internally but exposes the value via Context. The class component (Profile) consumes the context without using Hooks directly.

Method 4 – Use Render Props with Hooks

Render props is another classic React pattern that lets me pass Hook values into class components.

Here’s the code:

import React, { useState, useEffect } from "react";

// Functional component with render prop
function MouseTracker({ children }) {
  const [position, setPosition] = useState({ x: 0, y: 0 });

  useEffect(() => {
    const handleMouseMove = (e) => setPosition({ x: e.clientX, y: e.clientY });
    window.addEventListener("mousemove", handleMouseMove);
    return () => window.removeEventListener("mousemove", handleMouseMove);
  }, []);

  return children(position);
}

// Class component
class Dashboard extends React.Component {
  render() {
    return (
      <MouseTracker>
        {(pos) => (
          <h2>
            Mouse Position: X={pos.x}, Y={pos.y}
          </h2>
        )}
      </MouseTracker>
    );
  }
}

export default Dashboard;

The functional component MouseTracker uses Hooks to track mouse position. The class component receives those values via a render prop.

When Should You Use These Methods?

From my experience, I use HOCs when I want to add Hook logic to multiple class components. I go with wrapper functions when I just need one or two Hooks inside a single class.

For the global state, Context + Hooks is the cleanest solution. And sometimes, render props are the simplest answer when I don’t want to create extra context or HOCs.

Conclusion

Even though React Hooks don’t work directly in class components, there are several practical workarounds.

I’ve personally used HOCs, wrapper functions, Context, and render props in production projects. Each method has its own strengths, and the right choice depends on your use case.

If you’re working with a legacy codebase in the USA or anywhere else, you don’t need to rewrite everything into functional components right away. Instead, you can gradually introduce Hooks logic using these techniques.

You may also like to read:

Leave a Comment

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.