React Organizing Hooks

In the last lesson, React Organizing Components, you learned to keep components small and well-placed. This lesson does the same for custom hooks: where they live, how to name them, and how to split shared hooks from feature-specific ones.

🤔 Why organize hooks?

Custom hooks are great, but left unmanaged they get messy fast.

  • Hooks defined inside random component files are hard to find and reuse.
  • Two components reinvent the same logic because nobody could find the existing hook.
  • Hook files with vague names give no clue what they do.
  • Feature-specific hooks get mixed in with truly shared ones.

So organizing hooks is really about findability and reuse. Write a hook once, and everyone can find it.

📁 Give hooks a clear home

The simplest rule: put your custom hooks in a dedicated place, not scattered inside component files.

src/
hooks/
useFetch.js
useToggle.js
useLocalStorage.js

Here’s why a dedicated folder helps.

  • Anyone looking for a reusable hook knows to check hooks/.
  • It’s obvious where a new shared hook should go.
  • Hooks stay separate from components, so each file has one clear kind of thing.

📄 One hook per file

Like components, keep one main hook per file, named the same as the file.

  • useFetch.js exports useFetch. useToggle.js exports useToggle.
  • One hook per file makes each easy to locate and import.
  • The file name matches the hook name, so there are no surprises.

So when you need useToggle, you know it’s in useToggle.js. Predictable naming saves time, just like with components.

Keep the use prefix

Every custom hook still must start with use, both the function and ideally the file name. That prefix is what React’s tooling uses to check the rules of hooks, and it instantly signals “this is a hook”.

🗂️ Shared hooks vs feature hooks

Not every hook belongs in the global hooks/ folder, so split truly shared hooks from ones that only one feature uses.

  • Shared, generic hooks (like useFetch, useToggle) go in the top-level hooks/ folder.
  • Feature-specific hooks (like useAuth for the auth feature) live with that feature.
  • This matches the feature-folder idea from the folder-structure lesson.
src/
hooks/ // shared, generic
useFetch.js
useToggle.js
features/
auth/
useAuth.js // only the auth feature uses this

So the rule is simple. If many parts of the app would use a hook, put it in shared hooks/. If only one feature uses it, keep it in that feature’s folder.

🧩 Extract logic into hooks when it repeats

A quick reminder of when to make a hook, since that drives how many you’ll organize.

  • See the same useState plus useEffect logic in two components? Extract it into a hook.
  • A component getting cluttered with logic? Pull that logic into a hook to keep the component readable.
  • Don’t make a hook for logic used in only one place that isn’t cluttering anything.

So make hooks when logic repeats or when a component is getting heavy. That keeps your hook collection meaningful.

Don't abstract too early

Don’t create a custom hook the first time you write a piece of logic. Wait until you need it in a second place, or until it’s making a component hard to read. Premature hooks add files and indirection for no real gain.

⚠️ Common Mistakes

A common mistake is defining reusable hooks inside component files, so nobody can find or reuse them.

// ❌ a reusable hook buried inside a component file - hard to find and reuse
// in Dashboard.jsx
function useStats() { /* ... */ }
function Dashboard() { /* ... */ }
// ✅ move the shared hook to its own file in hooks/
// in hooks/useStats.js
export function useStats() { /* ... */ }

Keep these in mind.

  • Don’t bury reusable hooks inside component files. Give shared ones their own file in hooks/.
  • Don’t forget the use prefix on the function and file.
  • Don’t dump feature-only hooks into the global hooks/ folder; keep them with their feature.

✅ Best Practices

A few habits for organizing hooks.

  • Keep shared, generic hooks in a top-level hooks/ folder, one hook per file.
  • Keep feature-specific hooks inside that feature’s folder.
  • Name the file and the function the same, with the use prefix.
  • Extract a hook when logic repeats or clutters a component, not before.

Findable equals reusable

The whole point of a hook is reuse. If it’s hidden in some component file, nobody finds it and they rewrite the same logic. A clear hooks/ folder with predictable names is what makes your hooks actually get reused.

🧩 What You’ve Learned

  • ✅ Keep shared custom hooks in a dedicated hooks/ folder, not scattered in component files
  • ✅ Use one hook per file, with the file name matching the hook name
  • ✅ Keep the use prefix on both the function and the file
  • ✅ Put generic shared hooks in top-level hooks/; keep feature-only hooks with their feature
  • ✅ Extract a hook when logic repeats or clutters a component, not on the first use
  • ✅ Findable, well-named hooks are what make your logic actually get reused

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    Where should shared, generic custom hooks live?

    Why: A dedicated hooks/ folder with one hook per file makes shared hooks easy to find and reuse, and gives a clear home for new ones.

  2. 2

    Where should a hook that only one feature uses go?

    Why: Feature-specific hooks belong with their feature, matching the feature-folder approach. Only truly shared, generic hooks go in the global hooks/ folder.

  3. 3

    When should you extract logic into a custom hook?

    Why: Make a hook when logic repeats or makes a component hard to read. Extracting on the first use adds files and indirection for no real gain.

  4. 4

    Why is it bad to bury a reusable hook inside a component file?

    Why: A reusable hook hidden in a component file is hard to discover. People rewrite the same logic because they didn't know the hook existed.

🚀 What’s Next?

Now your hooks have a clear home and clear names. Next we’ll organize the code that talks to your backend, keeping all your API calls tidy in one place instead of scattered through components.

React Organizing API Calls

Share & Connect