Introduction to React Hooks: Modern State & Lifecycle Management in Functional Components
Last updated 2 months, 2 weeks ago | 123 views 75 5

Introduction: Why React Hooks Matter
Prior to React 16.8, developers had to rely on class components to manage state and lifecycle methods. This created unnecessary complexity, boilerplate code, and limited reusability.
React Hooks revolutionized the way developers write components by allowing stateful logic and side effects directly inside functional components—making your code simpler, cleaner, and more reusable.
With hooks, you can:
-
Use state in functional components
-
Perform side effects
-
Reuse logic with custom hooks
-
Avoid complex class syntax
Let’s dive into the essential hooks every React developer should know.
What Are React Hooks?
React Hooks are special functions that let you "hook into" React features such as state, context, and lifecycle from within functional components.
Key Rules of Hooks:
-
Hooks must be called at the top level of your component.
-
Hooks must be called from React functions, not regular JS functions.
-
Hooks are not used in class components.
Core React Hooks and How to Use Them
1️⃣ useState()
— For Managing Local Component State
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0); // Declare a state variable
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click Me</button>
</div>
);
}
-
useState()
returns a state value and a setter function. -
Calling the setter (e.g.,
setCount
) triggers a re-render.
2️⃣ useEffect()
— For Side Effects (API Calls, Subscriptions)
import React, { useState, useEffect } from 'react';
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds(prev => prev + 1); // increment seconds
}, 1000);
return () => clearInterval(interval); // cleanup on unmount
}, []); // empty dependency array = run once on mount
return <p>Timer: {seconds}s</p>;
}
-
useEffect()
runs after render. -
You can conditionally run effects based on dependencies.
-
Cleanup is handled via return function.
3️⃣ useContext()
— For Global State Using Context API
const ThemeContext = React.createContext();
function ThemedComponent() {
const theme = React.useContext(ThemeContext); // use context value
return <div style={{ backgroundColor: theme }}>Themed Box</div>;
}
-
Use with
React.createContext()
to avoid prop drilling. -
Best for themes, auth, and other global data.
4️⃣ useRef()
— For Referencing DOM or Persisting Values
import { useRef, useEffect } from 'react';
function FocusInput() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus(); // Auto-focus input on mount
}, []);
return <input ref={inputRef} type="text" />;
}
-
useRef()
gives you a mutable.current
object. -
Common use cases: accessing DOM elements, keeping previous values, or avoiding re-renders.
✅ Bonus: Custom Hooks
Create your own hook for reusable logic.
function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);
const increment = () => setCount(c => c + 1);
const reset = () => setCount(initialValue);
return { count, increment, reset };
}
Use it like this:
function Counter() {
const { count, increment, reset } = useCounter(5);
return (
<>
<p>Count: {count}</p>
<button onClick={increment}>+</button>
<button onClick={reset}>Reset</button>
</>
);
}
✅ Full Working Example Using Multiple Hooks
import React, { useState, useEffect, useRef } from 'react';
function App() {
const [count, setCount] = useState(0);
const inputRef = useRef(null);
useEffect(() => {
document.title = `You clicked ${count} times`; // side effect
}, [count]);
useEffect(() => {
inputRef.current.focus(); // auto-focus on mount
}, []);
return (
<div style={{ padding: 20 }}>
<h1>React Hooks Example</h1>
<input ref={inputRef} placeholder="Type here..." />
<p>You clicked {count} times</p>
<button onClick={() => setCount(c => c + 1)}>Click Me</button>
</div>
);
}
export default App;
⚠️ Tips & Common Pitfalls
✅ Best Practices
-
Always define hooks at the top of your function.
-
Use custom hooks for logic reuse.
-
Use multiple
useEffect()
hooks for separate concerns (not one mega-hook). -
Prefer
useCallback()
anduseMemo()
for performance-sensitive logic.
❌ Common Mistakes
-
Calling hooks inside loops or conditionals → ❌ Hooks must run in the same order on every render.
-
Forgetting dependency arrays in
useEffect()
→ leads to stale data or infinite loops. -
Overusing
useState()
for data that could live in context or a store.
Comparison Table: Class vs Hook-Based Component
Feature | Class Component | Functional Component (Hooks) |
---|---|---|
State Management | this.state , this.setState |
useState() |
Lifecycle | componentDidMount , etc. |
useEffect() |
DOM Access | createRef() |
useRef() |
Readability | Verbose | Cleaner and more concise |
Code Reuse | HOCs, Render Props | Custom Hooks |
Conclusion: Embrace the Power of Hooks
React Hooks provide a modern, elegant, and efficient way to write components by:
-
Eliminating class boilerplate
-
Encouraging logic reuse
-
Improving readability
Whether you're new to React or refactoring legacy code, Hooks should be your go-to for writing clean, modular, and scalable components.
Key Takeaways:
-
Use
useState
for local component state. -
Use
useEffect
for side effects like API calls and subscriptions. -
Use
useRef
,useContext
, and custom hooks to unlock advanced functionality. -
Follow the Rules of Hooks to avoid bugs and unpredictable behavior.