useAnything

Custom Hooks

function useMyLogic() { ... }

Extract component logic into reusable functions. If you find yourself copying `useEffect` or `useState` code between components, it's time for a hook.

Custom Hooks

A way to extract component logic into reusable functions. By convention, they always start with 'use'.

The Copy-Paste Trap

When multiple components need the same logic (e.g. checking if user is online), copying the useEffect code violates DRY.

Extraction

We move the state and effect into a standalone function: `useOnlineStatus`. Components just call it and get the value.

Return Structures

Custom hooks can return anything! A single value, an array (like useState), or an object containing data and functions.

Endless Possibilities

Window size, battery level, scroll position, API fetching... anything involving state and effects can be a hook.

Duplicate Logic

Imagine having 10 components that all need to know if the user is online. You'd have to copy this effect everywhere.

UserProfile.tsx
function UserProfile() {
  const [isOnline, setIsOnline] = useState(true);

  useEffect(() => {
    function handleOnline() { setIsOnline(true); }
    function handleOffline() { setIsOnline(false); }
    
    window.addEventListener('online', handleOnline);
    window.addEventListener('offline', handleOffline);
    
    return () => {
      window.removeEventListener('online', handleOnline);
      window.removeEventListener('offline', handleOffline);
    };
  }, []);

  return <div>{isOnline ? 'Online' : 'Offline'}</div>;
}
Boilerplate overload

The Custom Hook

Extract that logic into a function starting with `use`. Now it's reusable!

useOnlineStatus.ts
import { useState, useEffect } from 'react';

export function useOnlineStatus() {
  const [isOnline, setIsOnline] = useState(true);

  useEffect(() => {
    // ... logic to listen to "online"/"offline" events
  }, []);

  return isOnline;
}
Clean & Reusable
Components.tsx
function UserProfile() {
  const isOnline = useOnlineStatus();
  return <div>{isOnline ? 'Active' : 'Away'}</div>;
}

function StatusBar() {
  const isOnline = useOnlineStatus();
  return <div className={isOnline ? 'green' : 'red'} />;
}
Usage is simple!

Returning Values

You can return anything! Arrays are great if you want the user to rename variables (like useState). Objects are better if there are many values and order shouldn't matter.

useInput.ts (Array)
function useInput(initial) {
  const [val, setVal] = useState(initial);
  const onChange = e => setVal(e.target.value);
  
  // Return array: easy to rename!
  return [val, onChange]; 
}

// Consumer:
const [name, setName] = useInput("Alice");
const [email, setEmail] = useInput("");
Array Return
useFetch.ts (Object)
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  
  // ... fetch logic ...

  // Return object: named properties
  return { data, loading };
}

// Consumer:
const { data, loading } = useFetch("/api/user");
Object Return

Rules of Hooks Apply

Custom hooks are just functions that call other hooks. This means they must follow the same rules:

  • Must start with use (e.g. `useForm`, `useFetch`).
  • Call them at the top level of your component.
  • Don't call them inside loops or conditions.
AlgoAnimator: Interactive Data Structures