When building interactive UIs with React, two core concepts you must understand are state and lifecycle. These are what make React components dynamic, interactive, and responsive.
In this post, we’ll explore:
- What state is in React
- How lifecycle methods work
- The difference between class and functional components
- How to use hooks like
useStateanduseEffect
What is State in React?
In React, state refers to data that changes over time. It is managed within a component and can influence what gets rendered on the screen.
When the state of a component updates, React re-renders that component automatically.
Example: A Simple Counter Using useState
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0); // Declare state variable
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click Me
</button>
</div>
);
}
useState(0) initializes the state with 0.
setCount is the function used to update the state.
React re-renders the component every time count changes.
Understanding Lifecycle in React
Every React component goes through a lifecycle:
- Mounting – Component is being inserted into the DOM.
- Updating – Component updates due to changes in state or props.
- Unmounting – Component is removed from the DOM.
These phases allow us to hook into key moments of a component’s existence.
Lifecycle Methods in Class Components
React class components come with lifecycle methods that allow you to run code at specific times.
| Method | Description |
|---|---|
componentDidMount() | Runs after the component is added to the DOM |
componentDidUpdate() | Runs after an update happens |
componentWillUnmount() | Runs before the component is removed |
Example: Timer Component Using Class
class Timer extends React.Component {
constructor(props) {
super(props);
this.state = { seconds: 0 };
}
componentDidMount() {
this.interval = setInterval(() => {
this.setState(prev => ({ seconds: prev.seconds + 1 }));
}, 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
}
render() {
return <p>Seconds: {this.state.seconds}</p>;
}
}
Lifecycle in Functional Components with Hooks
With React Hooks, you can achieve the same lifecycle behavior in functional components using the useEffect hook.
Example: Timer with useEffect
import React, { useState, useEffect } from 'react';
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds(prev => prev + 1);
}, 1000);
return () => clearInterval(interval); // Cleanup on unmount
}, []);
return <p>Seconds: {seconds}</p>;
}
useEffect with an empty dependency array ([]) acts like componentDidMount.
The return function handles cleanup, similar to componentWillUnmount.
State vs Props: Key Differences
| Feature | State | Props |
|---|---|---|
| Owned by | The component itself | The parent component |
| Mutability | Mutable | Immutable |
| Usage | Manage local data | Pass data to child components |
Why Are State and Lifecycle Important?
Mastering state and lifecycle is essential to:
- Build dynamic interfaces
- Handle asynchronous events
- Manage API calls
- Optimize performance with controlled re-renders
- Avoid memory leaks with proper cleanup
Related Concepts to Explore
- React Context for global state
- Custom hooks for reusable logic
- React Router for navigation
- Performance optimization with
React.memoanduseCallback
Final Thoughts
React is powerful because it reacts to state changes and renders UI dynamically. To build responsive and maintainable applications, understanding state and lifecycle is non-negotiable.
Whether you’re using class components or modern functional components with hooks, these tools are the foundation of every interactive React app.
