Getting Weird: "Hooks" in React Class Components
Published: 2024-04-21 03:34:44

---
title: Getting Weird: "Hooks" in React Class Components
published: true
description: How you can leverage "hooks" in class components and avoid the odd rules of React hooks and Higher Order Components 
tags: 
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2024-03-12 03:41 +0000
---
Before we begin.  I know: Class Components are toast. They're dead and they ain't coming back.  I'm just messing around in this post... so let's get weird.

We're going to create a contrived example of two components that will fetch the same data. The "hook" created will be a fetch call that exposes data to state. 



Here's the Codesandbox: <a href="https://codesandbox.io/p/sandbox/class-component-hoods-w65z2l?layout=%257B%2522sidebarPanel%2522%253A%2522EXPLORER%2522%252C%2522rootPanelGroup%2522%253A%257B%2522direction%2522%253A%2522horizontal%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522id%2522%253A%2522ROOT_LAYOUT%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522clv8xt6s00006356f5cro3gu7%2522%252C%2522sizes%2522%253A%255B100%252C0%255D%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522EDITOR%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522id%2522%253A%2522clv8xt6s00002356frzw51onp%2522%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522SHELLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522id%2522%253A%2522clv8xt6s00003356f0c501ul1%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522DEVTOOLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522id%2522%253A%2522clv8xt6s00005356fnwimrpre%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%252C%2522sizes%2522%253A%255B50%252C50%255D%257D%252C%2522tabbedPanels%2522%253A%257B%2522clv8xt6s00002356frzw51onp%2522%253A%257B%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clv8xt6rz0001356frjdykidz%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522FILE%2522%252C%2522filepath%2522%253A%2522%252Fsrc%252Findex.tsx%2522%257D%255D%252C%2522id%2522%253A%2522clv8xt6s00002356frzw51onp%2522%252C%2522activeTabId%2522%253A%2522clv8xt6rz0001356frjdykidz%2522%257D%252C%2522clv8xt6s00005356fnwimrpre%2522%253A%257B%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clv8xt6s00004356focz86ee6%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522UNASSIGNED_PORT%2522%252C%2522port%2522%253A0%252C%2522path%2522%253A%2522%252F%2522%257D%255D%252C%2522id%2522%253A%2522clv8xt6s00005356fnwimrpre%2522%252C%2522activeTabId%2522%253A%2522clv8xt6s00004356focz86ee6%2522%257D%252C%2522clv8xt6s00003356f0c501ul1%2522%253A%257B%2522tabs%2522%253A%255B%255D%252C%2522id%2522%253A%2522clv8xt6s00003356f0c501ul1%2522%257D%257D%252C%2522showDevtools%2522%253Atrue%252C%2522showShells%2522%253Afalse%252C%2522showSidebar%2522%253Atrue%252C%2522sidebarPanelSize%2522%253A15%257D" target="_blank">click me!</a>

## The "Hook"
```ts
export async function useTodos() {
  this.setState({
    fetching: true,
  });

  const resp = await fetch("https://jsonplaceholder.typicode.com/todos");
  const data = await resp.json();
  this.setState({
    todos: data,
    todoCount: data.length,
  });
}
```

The above code simply fetches data and assigns it to state.  `this` is nebulous at this point.  It will refer to the housing function. But we'll assign the context of `this` in the next code snippet.

## Component 1
```ts
import React from "react";
import { useTodos } from "./hooks";

export default class TodoCounter extends React.Component {
  constructor(props) {
    super(props);
  }

  UNSAFE_componentWillMount(): void {
    useTodos.call(this);
  }

  render() {
    return (
      <div>
        <p>Todos: {this.state?.todoCount}</p>
      </div>
    );
  }
}
```
Here we are assigning the value of `this` in the hook by using `call` in the component. 

Note how you don't even have to define state here to access the hook data.

And (like hooks) you can use this in other components

```ts
import React from "react";
import { useTodos } from "./hooks";

export default class TodoList extends React.Component {
  constructor(props) {
    super(props);
  }

  UNSAFE_componentWillMount(): void {
    useTodos.call(this);
  }

  render() {
    return (
      <ol>
        {this.state.todos?.map((todo, i) => {
          return <li key={i}>{todo.title}</li>;
        })}
      </ol>
    );
  }
}
```

So yeah, it's super stupid. But you could use "hooks" all along with class components.  We got weird.  

---

Side note: I hate functional components.  I think the lifecycle methods of class components map more closely to how DOM and web component lifecycles work.  But React is ditching all of that for their functional approach. That's fine. But I'm just switching over to StencilJS instead.  I prefer my OOP.