React Hooks have revolutionized how we write React components. In this article, we’ll explore basic hooks and how to apply them in real-world projects.
Basic Hooks
1. useState Hook
useState is the most basic hook, helping manage state in functional components:
import React, { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
2. useEffect Hook
useEffect replaces lifecycle methods in class components:
import React, { useState, useEffect } from "react";
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds((seconds) => seconds + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
return <div>Timer: {seconds}s</div>;
}
Advanced Hooks
1. useContext Hook
useContext helps consume Context values easily:
import React, { useContext } from "react";
import { ThemeContext } from "./ThemeContext";
function ThemedButton() {
const theme = useContext(ThemeContext);
return (
<button style={{ background: theme.background }}>Themed Button</button>
);
}
2. useReducer Hook
useReducer is useful for complex state management:
import React, { 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 };
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
Count: {state.count}
<button onClick={() => dispatch({ type: "increment" })}>+</button>
<button onClick={() => dispatch({ type: "decrement" })}>-</button>
</div>
);
}
Best Practices
1. Custom Hooks
Create reusable logic with custom hooks:
import { useState, useEffect } from "react";
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) {
console.error(error);
}
};
return [storedValue, setValue];
}
2. Performance Optimization
Use useMemo and useCallback for performance:
import React, { useMemo, useCallback } from "react";
function ExpensiveComponent({ items, onItemClick }) {
const expensiveValue = useMemo(() => {
return items.reduce((sum, item) => sum + item.value, 0);
}, [items]);
const handleClick = useCallback(
(id) => {
onItemClick(id);
},
[onItemClick],
);
return (
<div>
<p>Total: {expensiveValue}</p>
{items.map((item) => (
<button key={item.id} onClick={() => handleClick(item.id)}>
{item.name}
</button>
))}
</div>
);
}
Conclusion
React Hooks provide a powerful and flexible way to manage state and side effects in functional components. By mastering these hooks, you can write cleaner, more reusable code that’s easier to test and maintain.
Remember to:
- Use the right hook for your use case
- Follow the Rules of Hooks
- Create custom hooks for reusable logic
- Optimize performance when necessary
Happy coding with React Hooks! 🚀
