REACT HOOKS: The Simplified Guide
Hooks allow functions to have access to state and other React features without using classes. You can either use the built-in Hooks or combine them to build your own.
Rules of Hooks
Before you start, you must follow these rules or your app will break:
- Only call Hooks at the top level: Don’t call Hooks inside loops, conditions, or nested functions.
- Only call Hooks from React functions: Use them in functional components or custom Hooks, never in regular JavaScript functions or class components.
- Hooks cannot be conditional: The order of Hook calls must stay the same on every render. (e.g., inside an if statement)
- Importing: You must always import them first from the React library before usage.
useState
The Simplified Concept: State lets a component “remember” information like user input. For example, a form component uses state to store what you type.
Syntax:
const [state, setState] = useState(initialValue);When to use:
Tracking strings, numbers, booleans, arrays, or objects that need to change on the screen.
Example (Updating an Array):
const [names, setNames] = useState([]);
setNames(["Alice", "Bob"]);useEffect
The Simplified Concept: Your component’s main job is just to show things. But sometimes, it needs to do something extra “on the side” — like call an API or start a countdown. These are called Side Effects.
Syntax:
useEffect(() =>
{
/* logic */
}, [dependencyArray]);Example
function UserProfile() {
const [user, setUser] = useState(null);
useEffect(() => {
// This runs once when the component "mounts" (appears)
fetch("https://api.example.com/user/1")
.then((response) => response.json())
.then((data) => setUser(data));
}, []); // The empty array [] means "only run once"
if (!user) return <p>Loading...</p>;
return <h1>Hello, {user.name}!</h1>;
}When to use: Fetching data, starting timers, or listening for keyboard input.
The Dependency Rule:
- Empty Array []: Runs once when the component first appears.
- With Values [count]: Runs only when that specific value changes.
- No Array: Runs after every single render (not recommended for performance).
UseRef
The Simplified Concept: useRef is like a sticky note you keep on the side. You can write on it and update it anytime, but React doesn’t “notice” or redraw the screen when you do. It also lets you “reach into” the HTML.
Get Egbalajoy’s stories in your inbox
Join Medium for free to get updates from this writer.
Syntax:
const myRef = useRef(initialValue);When to use:
- Focusing an input field programmatically.
- Storing a timer ID to clear it later.
- Remembering a value without refreshing the UI
Example
const inputRef = useRef(null);
// This reaches into the DOM to focus the box
const focusInput = () => inputRef.current.focus();
return <input ref={inputRef} />;useMemo
The Simplified Concept: This remembers the result of a heavy calculation (like sorting 200,000 items). It tells React: “Only redo this work if these specific values changed. Otherwise, just give me the saved result from last time.”
Syntax:
const result = useMemo(() => expensiveFunction(), [dependencies]);When to use:
Sorting/filtering large lists or doing complex math that slows down your app.
Example(filtering large list):
import { useMemo, useState } from "react";
function ProductList({ products }) {
const [query, setQuery] = useState("");
// This "expensive" filter only runs when 'products' or 'query' changes
const filteredProducts = useMemo(() => {
console.log("Filtering items..."); // You'll see this only when necessary
return products.filter(p => p.name.includes(query));
}, [products, query]);
return (
<>
<input onChange={(e) => setQuery(e.target.value)} placeholder="Search..." />
<ul>
{filteredProducts.map(p => <li key={p.id}>{p.name}</li>)}
</ul>
</>
);
}useContext
Normally in React, if a parent has data and a deeply nested child needs it, you have to pass it down through every component in between even the ones that don’t use it. This is called prop drilling. useContext fixes this by letting you put data in one central place, and any component anywhere in your app can just grab it directly no need to drill it down through multiple layers
Syntax:
const value = useContext(MyContext);When to use:
- Logged-in user info.
- Theme preference (Dark/Light mode).
- App language settings.
- Anything many components across your app need to know
Example
const ThemeContext = createContext('light');
function Display() {
const theme = useContext(ThemeContext);
return <div className={theme}>The current theme is {theme}</div>;
}useCallback
While useMemo returns a value, useCallback returns a memoized function. .Memoizing a function means caching the result of a function so that it does not need to be recalculated.
The useCallback function only re-executes when one of its dependencies changes value.
Syntax
useCallback(callback, dependencies)Where:
callback: The function that you want to memoize.
dependencies: An array of dependencies for the callback function. The memoized callback will only change if one of these dependencies has changed.
When to use: Passing functions to optimized child components (React.memo) to prevent them from re-rendering unnecessarily.
Example
const memoizedHandleClick = useCallback(() => {
console.log("Button clicked!");
}, []); // This function identity stays the same across renders







