Notes on Functions, Hooks, and Custom Hooks in React
1. Normal Functions in JavaScript
- A normal function is used to perform operations or return values.
- Example:
function add(a, b) {
return a + b;
}
console.log(add(2, 3)); // 5
- Functions work well for logic that does not depend on React’s rendering system.
- 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
- React applications are UI driven by state and props.
- A normal variable update (with a function) will not tell React to re-render the component.
- 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>
);
}
- Even if
countincreases, the UI always shows0. - 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>
);
}
- Here,
useStatetells React that the component has state. - When
setCountis called, React re-renders the component and updates the UI.
3. Rules of Hooks
- Hooks must be called at the top level of a component or custom hook.
- Hooks must only be called inside React functions (components or custom hooks).
- Examples of built-in hooks:
useState→ manage state.useEffect→ handle side effects.useContext→ access global context.useRef→ persist values without causing re-renders.
4. Why Custom Hooks?
- Often, multiple components need the same logic (e.g., fetching data, managing forms).
- If you repeat that logic in every component, your code becomes messy and hard to maintain.
- 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>;
}
- 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>;
}
- Logic is written once in
useFetch. - Both components stay small and easy to read.
- You can reuse
useFetchanywhere in the app.
5. When to Use Functions vs Hooks vs Custom Hooks
- Normal Function:
- Use for logic that does not involve React state or lifecycle.
- Example: formatting a string, calculating a number, sorting an array.
- Built-in Hooks:
- Use when you need to manage state, effects, refs, or context in a component.
- Example:
useStateto store a counter,useEffectto fetch data when a component mounts. - Custom Hooks:
- Use when you want to reuse hook-based logic across multiple components.
- They help keep code DRY (Don’t Repeat Yourself) and components clean.
- Example:
useFetch,useLocalStorage,useAuth.
6. Key Takeaways
- A plain function can update variables, but React does not re-render on variable changes.
- Hooks (
useState,useEffect, etc.) are React’s way of tracking state and lifecycle, ensuring UI updates automatically. - Custom hooks are just functions that use built-in hooks to encapsulate reusable stateful logic.
- Use functions for pure logic, built-in hooks for stateful logic, and custom hooks for reusable stateful logic.