Notes on Functions, Hooks, and Custom Hooks in React

1. Normal Functions in JavaScript

  1. A normal function is used to perform operations or return values.
  2. Example:
function add(a, b) {
return a + b;
}
console.log(add(2, 3)); // 5
  1. Functions work well for logic that does not depend on React’s rendering system.
  2. In React, you can use functions to format data, calculate results, or transform values, but they cannot manage component state or lifecycle.

2. Why Hooks Are Needed

  1. React applications are UI driven by state and props.
  2. A normal variable update (with a function) will not tell React to re-render the component.
  3. Hooks are special functions that let you “hook into” React’s state and lifecycle features inside functional components.

Example: Without Hooks

function Counter() {
let count = 0;

function increment() {
count++;
console.log(count);
}

return (
<div>
<p>{count}</p>
<button onClick={increment}>Increment</button>
</div>
);
}
  1. Even if count increases, the UI always shows 0.
  2. Reason: React does not track changes to normal variables.

Example: With Hooks

import { useState } from "react";

function Counter() {
const [count, setCount] = useState(0);

return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
  1. Here, useState tells React that the component has state.
  2. When setCount is called, React re-renders the component and updates the UI.

3. Rules of Hooks

  1. Hooks must be called at the top level of a component or custom hook.
  2. Hooks must only be called inside React functions (components or custom hooks).
  3. Examples of built-in hooks:
  4. useState → manage state.
  5. useEffect → handle side effects.
  6. useContext → access global context.
  7. useRef → persist values without causing re-renders.

4. Why Custom Hooks?

  1. Often, multiple components need the same logic (e.g., fetching data, managing forms).
  2. If you repeat that logic in every component, your code becomes messy and hard to maintain.
  3. A custom hook lets you extract and reuse this logic.

Example Without Custom Hook (repetition)

import { useState, useEffect } from "react";

function User() {
const [user, setUser] = useState(null);

useEffect(() => {
fetch("/api/user")
.then(res => res.json())
.then(data => setUser(data));
}, []);

return <div>{user?.name}</div>;
}

function Posts() {
const [posts, setPosts] = useState([]);

useEffect(() => {
fetch("/api/posts")
.then(res => res.json())
.then(data => setPosts(data));
}, []);

return <div>{posts.length} posts</div>;
}
  1. Both components repeat fetching logic.

Example With Custom Hook (clean and reusable)

import { useState, useEffect } from "react";

function useFetch(url) {
const [data, setData] = useState(null);

useEffect(() => {
fetch(url)
.then(res => res.json())
.then(json => setData(json));
}, [url]);

return data;
}

function User() {
const user = useFetch("/api/user");
return <div>{user?.name}</div>;
}

function Posts() {
const posts = useFetch("/api/posts");
return <div>{posts?.length} posts</div>;
}
  1. Logic is written once in useFetch.
  2. Both components stay small and easy to read.
  3. You can reuse useFetch anywhere in the app.

5. When to Use Functions vs Hooks vs Custom Hooks

  1. Normal Function:
  2. Use for logic that does not involve React state or lifecycle.
  3. Example: formatting a string, calculating a number, sorting an array.
  4. Built-in Hooks:
  5. Use when you need to manage state, effects, refs, or context in a component.
  6. Example: useState to store a counter, useEffect to fetch data when a component mounts.
  7. Custom Hooks:
  8. Use when you want to reuse hook-based logic across multiple components.
  9. They help keep code DRY (Don’t Repeat Yourself) and components clean.
  10. Example: useFetch, useLocalStorage, useAuth.

6. Key Takeaways

  1. A plain function can update variables, but React does not re-render on variable changes.
  2. Hooks (useState, useEffect, etc.) are React’s way of tracking state and lifecycle, ensuring UI updates automatically.
  3. Custom hooks are just functions that use built-in hooks to encapsulate reusable stateful logic.
  4. Use functions for pure logic, built-in hooks for stateful logic, and custom hooks for reusable stateful logic.