Introduction
React Hooks revolutionized how we write React components. Introduced in React 16.8, hooks allow you to use state and other React features without writing a class. In this comprehensive guide, we'll explore all the essential hooks and advanced patterns.
Why Hooks?
Before hooks, stateful logic was tied to class components. This led to:
- Complex components that were hard to understand
- Confusing
thisbinding in JavaScript - Difficulty reusing stateful logic between components
Hooks solve these problems by letting you use state and lifecycle features in functional components.
useState: Managing State
The most fundamental hook. It lets you add state to functional components.
javascript
Copy
1import { useState } from 'react'; 2 3function Counter() { 4 const [count, setCount] = useState(0); 5 6 return ( 7 <div> 8 <p>Count: {count}</p> 9 <button onClick={() => setCount(count + 1)}>10 Increment11 </button>12 </div>13 );14}
#
Best Practices for useState
1. Use multiple state variables for unrelated data
2. Group related state in objects
3. Use functional updates when new state depends on old state
useEffect: Side Effects
useEffect handles side effects like data fetching, subscriptions, and DOM manipulation.
javascript
const data = await response.json();
setUser(data);
setLoading(false);
}
fetchUser();
}, [userId]); // Dependency array
if (loading) return <div>Loading...</div>;
return <div>{user.name}</div>;
}">
Copy
1import { useState, useEffect } from 'react'; 2 3function UserProfile({ userId }) { 4 const [user, setUser] = useState(null); 5 const [loading, setLoading] = useState(true); 6 7 useEffect(() => { 8 async function fetchUser() { 9 setLoading(true);10 const response = await fetch(/api/users/${userId});11 const data = await response.json();12 setUser(data);13 setLoading(false);14 }15 16 fetchUser();17 }, [userId]); // Dependency array1819 if (loading) return <div>Loading...</div>;20 return <div>{user.name}</div>;21}
#
Cleanup Functions
Always clean up subscriptions and timers:
javascript
Copy
1useEffect(() => { 2 const subscription = props.source.subscribe(); 3 return () => { 4 subscription.unsubscribe(); 5 }; 6}, [props.source]);
useContext: Sharing State
Share state across components without prop drilling.
javascript
Copy
1import { createContext, useContext, useState } from 'react'; 2 3const ThemeContext = createContext(); 4 5function ThemeProvider({ children }) { 6 const [theme, setTheme] = useState('dark'); 7 8 return ( 9 <ThemeContext.Provider value={{ theme, setTheme }}>10 {children}11 </ThemeContext.Provider>12 );13}1415function ThemedButton() {16 const { theme, setTheme } = useContext(ThemeContext);17 18 return (19 <button 20 style={{ background: theme === 'dark' ? '#333' : '#fff' }}21 onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}22 >23 Toggle Theme24 </button>25 );26}
Custom Hooks
Extract reusable logic into custom hooks.
javascript
Copy
1function useLocalStorage(key, initialValue) { 2 const [storedValue, setStoredValue] = useState(() => { 3 try { 4 const item = window.localStorage.getItem(key); 5 return item ? JSON.parse(item) : initialValue; 6 } catch (error) { 7 return initialValue; 8 } 9 });1011 const setValue = (value) => {12 setStoredValue(value);13 window.localStorage.setItem(key, JSON.stringify(value));14 };1516 return [storedValue, setValue];17}1819// Usage20const [name, setName] = useLocalStorage('name', 'Guest');
Conclusion
React Hooks provide a powerful and clean way to manage state and side effects. Master these patterns and you'll write more maintainable React applications.