React Hooks Complete Guide: useState, useEffect, and Best Practices 2025
React Hooks Complete Guide: useState, useEffect, and Best Practices 2025
React Hooks revolutionized React development by allowing functional components to manage state and side effects. This comprehensive guide covers everything you need to know about React Hooks in 2025.
What are React Hooks?
React Hooks are functions that let you "hook into" React features from functional components. Introduced in React 16.8, hooks allow you to use state and other React features without writing class components.
Why Use Hooks?
Basic React Hooks
1. useState Hook
useState allows functional components to manage local state:
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setCount(count - 1)}>Decrement</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
}useState with Objects:
function UserForm() {
const [user, setUser] = useState({
name: '',
email: '',
age: 0
});
const handleChange = (e) => {
setUser({
...user,
[e.target.name]: e.target.value
});
};
return (2. useEffect Hook
useEffect handles side effects in functional components:
import { useState, useEffect } from 'react';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchUser() {
setLoading(true);
const response = await fetch(`/api/users/${userId}`);
const data = await response.json();
setUser(data);
setLoading(false);
}
useEffect Cleanup:
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds(prev => prev + 1);
}, 1000);
// Cleanup function
return () => clearInterval(interval);
}, []); // Run once on mount
return <div>Seconds: {seconds}</div>;
}3. useContext Hook
useContext accesses React context values:
import { createContext, useContext } from 'react';
const ThemeContext = createContext('light');
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar() {
const theme = useContext(ThemeContext);
return <div className={`theme-${theme}`}>Toolbar</div>;4. useReducer Hook
useReducer manages complex state logic:
import { useReducer } from 'react';
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
case 'reset':
return initialState;
default:
throw new Error();
}Custom Hooks
Create reusable hooks for common logic:
// Custom hook for API fetching
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchData() {
try {
setLoading(true);
const response = await fetch(url);
const json = await response.json();
setData(json);
setError(null);
} catch (err) {Custom Hook for Local Storage:
function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
return initialValue;
}
});
const setValue = (value) => {
try {
setStoredValue(value);
window.localStorage.setItem(key, JSON.stringify(value));
} catch (error) {Advanced Hooks
useMemo Hook
useMemo memoizes expensive calculations:
import { useMemo } from 'react';
function ExpensiveComponent({ items, filter }) {
const filteredItems = useMemo(() => {
return items.filter(item => item.category === filter);
}, [items, filter]); // Recalculate only when items or filter change
return (
<ul>
{filteredItems.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}useCallback Hook
useCallback memoizes functions:
import { useCallback, useState } from 'react';
function ParentComponent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log('Clicked!', count);
}, [count]); // Recreate function only when count changes
return <ChildComponent onClick={handleClick} />;
}
function ChildComponent({ onClick }) {
return <button onClick={onClick}>Click me</button>;
}useRef Hook
useRef persists values across renders:
import { useRef, useEffect } from 'react';
function FocusInput() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, []);
return <input ref={inputRef} type="text" />;
}React Hooks Best Practices
1. Follow Rules of Hooks
// Bad - Conditional hook
function Component({ condition }) {
if (condition) {
const [value, setValue] = useState(0); // Wrong!
}
return <div>Component</div>;
}
// Good - Always call hooks at top level
function Component({ condition }) {
const [value, setValue] = useState(0);
if (condition) {
// Use condition in logic, not in hook call
}2. Optimize useEffect Dependencies
Always include all dependencies in the dependency array:
// Bad - Missing dependency
useEffect(() => {
fetchData(userId);
}, []); // Missing userId
// Good - All dependencies included
useEffect(() => {
fetchData(userId);
}, [userId]);3. Cleanup Side Effects
Always cleanup subscriptions, timers, and event listeners:
useEffect(() => {
const subscription = subscribe();
const timer = setInterval(() => {}, 1000);
window.addEventListener('resize', handleResize);
return () => {
subscription.unsubscribe();
clearInterval(timer);
window.removeEventListener('resize', handleResize);
};
}, []);4. Use Custom Hooks for Reusability
Extract common logic into custom hooks:
// Custom hook
function useDebounce(value, delay) {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const timer = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => clearTimeout(timer);
}, [value, delay]);
return debouncedValue;
}
Common React Hooks Patterns
Form Handling Hook:
function useForm(initialValues) {
const [values, setValues] = useState(initialValues);
const [errors, setErrors] = useState({});
const handleChange = (e) => {
const { name, value } = e.target;
setValues({ ...values, [name]: value });
};
const handleSubmit = (onSubmit) => (e) => {
e.preventDefault();
onSubmit(values);
};
return { values, errors, handleChange, handleSubmit };React Hooks Tools
Online React Hook Generator
Codev Nexus React Hook Generator - Free, instant React hook generation:
Try it: [codevnexus.com/tools/react-hook-generator](https://codevnexus.com/tools/react-hook-generator)
Conclusion
React Hooks provide a powerful and elegant way to manage state and side effects in functional components. Understanding hooks is essential for modern React development.
Key Takeaways:
Start using React Hooks today to write cleaner, more maintainable React code!
Resources
Master React Hooks for modern React development!
Share this article
Help others discover this content
Enjoyed this article?
Support our work and help us create more free content for developers.
Stay Updated
Get the latest articles and updates delivered to your inbox.