React Hooks Explained
A comprehensive guide to understanding and using React Hooks effectively in your projects.
Introduction to React Hooks
React Hooks were introduced in React 16.8 as a way to use state and other React features without writing a class. They allow you to “hook into” React state and lifecycle features from function components, making code more reusable and easier to understand.
Why Hooks?
Before Hooks, if you wanted to add state to a component, you had to use a class component. Hooks solve several problems that React developers faced:
- Reusing stateful logic between components was difficult
- Complex components became hard to understand
- Classes confused both people and machines (this binding, boilerplate code)
Basic Hooks
useState
The useState
hook lets you add state to function 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>
);
}
useEffect
The useEffect
hook lets you perform side effects in function components:
import React, { useState, useEffect } from 'react';
function Example() {
const [data, setData] = useState(null);
useEffect(() => {
// This runs after render and when dependencies change
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => setData(data));
// Optional cleanup function
return () => {
// Cleanup code here
};
}, [/* dependencies array */]);
return (
<div>{data ? JSON.stringify(data) : 'Loading...'}</div>
);
}
useContext
The useContext
hook lets you subscribe to React context without introducing nesting:
import React, { useContext } from 'react';
const ThemeContext = React.createContext('light');
function ThemedButton() {
const theme = useContext(ThemeContext);
return <button className={theme}>Themed Button</button>;
}
Additional Hooks
- useReducer: An alternative to useState for complex state logic
- useCallback: Returns a memoized callback function
- useMemo: Returns a memoized value
- useRef: Creates a mutable ref object that persists across renders
- useLayoutEffect: Similar to useEffect, but fires synchronously after all DOM mutations
- useDebugValue: Used to display a label in React DevTools
Custom Hooks
One of the most powerful features of Hooks is the ability to create your own. Custom Hooks let you extract component logic into reusable functions:
// Custom Hook for form handling
function useFormInput(initialValue) {
const [value, setValue] = useState(initialValue);
function handleChange(e) {
setValue(e.target.value);
}
return {
value,
onChange: handleChange
};
}
// Using the custom Hook
function SignupForm() {
const email = useFormInput('');
const password = useFormInput('');
return (
<form>
<input type="email" {...email} />
<input type="password" {...password} />
<button type="submit">Sign Up</button>
</form>
);
}
Rules of Hooks
To ensure Hooks work correctly, you must follow two rules:
- Only call Hooks at the top level (not inside loops, conditions, or nested functions)
- Only call Hooks from React function components or custom Hooks