Components can have state (state), which is a private part of the component's data and can be used to manage dynamic data.
State is only applicable to class components, or can be used in function components when using React's Hooks.
React views components as state machines (State Machines). Through interaction with the user, it achieves different states, then renders the UI, keeping the user interface and data consistent.
In React, you only need to update the component's state, and then re-render the user interface based on the new state (do not manipulate the DOM).
The following example creates an ES6 class that extends React.Component, using this.state in the render() method to modify the current time.
Add a class constructor to initialize the state this.state. Class components should always call the base constructor with props.
* * *
### State Management in Class Components
Create a stateful class component:
## Counter.js File
import React,{ Component } from 'react';
class Counter extends Component {
constructor(props){
super(props);
this.state={ count:0};
}
increment =()=>{
this.setState({ count:this.state.count+1});
}
render(){
return(
Count:{this.state.count}
);
}
}
export default Counter;
Render this component in src/index.js:
## Example
import React from 'react';
import ReactDOM from 'react-dom';
import'./index.css';
import Counter from './Counter';
const root = ReactDOM.createRoot(document.getElementById("root"));
// Render the Counter component
root.render();
### State Management in Function Components (Using Hook)
You can use state in function components using React Hook. The most commonly used Hook is useState.
Create a stateful function component:
## Counter.js File
import React,{ useState } from 'react';
function Counter(){
const[count, setCount]= useState(0);
return(
Count:{count}
);
}
export default Counter;
Render this component in src/index.js:
## Example
import React from 'react';
import ReactDOM from 'react-dom';
import'./index.css';
import Counter from './Counter';
const root = ReactDOM.createRoot(document.getElementById("root"));
// Render the Counter component
root.render();
* * *
## Example
Create a time example to understand component state:
## React Example
class Clock extends React.Component{constructor(props){super(props); this.state = {date: new Date()}; }render(){return(
Hello, world!
It is now {this.state.date.toLocaleTimeString()}.
); }}const root = ReactDOM.createRoot(document.getElementById("root")); root.render();
[Try it Β»](#)
Next, we will make the Clock set its own timer and update every second.
### Adding Lifecycle Methods to a Class
In applications with many components, it is important to free up resources occupied by components when they are destroyed.
Every time the Clock component is first loaded into the DOM, we want to generate a timer. This is called **mounting** in React.
Similarly, every time the DOM generated by this Clock is removed, we also want to clear the timer. This is called **unmounting** in React.
We can declare special methods on the component class to run some code when the component mounts or unmounts:
## React Example
class Clock extends React.Component{constructor(props){super(props); this.state = {date: new Date()}; }componentDidMount(){this.timerID = setInterval(() =>this.tick(), 1000); }componentWillUnmount(){clearInterval(this.timerID); }tick(){this.setState({date: new Date()}); }render(){return(
Hello, world!
It is now {this.state.date.toLocaleTimeString()}.
); }}const root = ReactDOM.createRoot(document.getElementById("root")); root.render();
[Try it Β»](#)
**Example Analysis:**
The `componentDidMount()` and `componentWillUnmount()` methods are called lifecycle hooks.
The `componentDidMount()` hook is executed after the component output is rendered to the DOM. We can set up a timer in this hook.
`this.timerID` is the ID of the timer, which we can clear in the `componentWillUnmount()` hook.
**Code Execution Order:**
1. When `` is passed to `ReactDOM.render()`, React calls the constructor of the `Clock` component. Since `Clock` needs to display the current time, it initializes `this.state` with an object containing the current time. We will update this state later.
2. React then calls the `render()` method of the `Clock` component. This is how React knows what should be displayed on the screen, and then React updates the DOM to match the rendered output of `Clock`.
3. When the output of `Clock` is inserted into the DOM, React calls the `componentDidMount()` lifecycle hook. Inside it, the `Clock` component asks the browser to set up a timer to call `tick()` every second.
4. The browser calls the `tick()` method every second. Inside it, the `Clock` component schedules a UI update by calling `setState()` with an object containing the current time. By calling `setState()`, React knows that the state has changed and calls the `render()` method again to determine what should be displayed on the screen. This time, `this.state.date` in the `render()` method will be different, so the rendered output will include the updated time, and the DOM is updated accordingly.
5. Once the `Clock` component is removed from the DOM, React calls the `componentWillUnmount()` hook, and the timer is cleared.
### Data Flows Downwards
Neither parent nor child components know whether a component is stateful or stateless, and they shouldn't care whether a component is defined as a function or a class.
This is why state is often called local or encapsulated. It is not accessible to any component other than the one that owns and sets it.
In the following example, the `FormattedDate` component will receive the `date` value in its props and doesn't know whether it comes from the Clock's state, from the Clock's props, or is manually entered:
## React Example
function FormattedDate(props){return
It is now {props.date.toLocaleTimeString()}.
; }class Clock extends React.Component{constructor(props){super(props); this.state = {date: new Date()}; }componentDidMount(){this.timerID = setInterval(() =>this.tick(), 1000); }componentWillUnmount(){clearInterval(this.timerID); }tick(){this.setState({date: new Date()}); }render(){return(
Hello, world!
); }}const root = ReactDOM.createRoot(document.getElementById("root")); root.render();
[Try it Β»](#)
This is often called "top-down" or "unidirectional data flow." Any state is always owned by some specific component, and any data or UI derived from that state can only affect components "down" the tree.
If you imagine a component tree as a waterfall of props, each component's state is like an additional water source that joins it at an arbitrary point but also flows down.
To show that all components are truly isolated, we can create an App component that renders three Clocks:
## React Example
function FormattedDate(props){return
It is now {props.date.toLocaleTimeString()}.
; }class Clock extends React.Component{constructor(props){super(props); this.state = {date: new Date()}; }componentDidMount(){this.timerID = setInterval(() =>this.tick(), 1000); }componentWillUnmount(){clearInterval(this.timerID); }tick(){this.setState({date: new Date()}); }render(){return(
Hello, world!
); }}function App(){return(); }const root = ReactDOM.createRoot(document.getElementById("root")); root.render();
[Try it Β»](#)
In the example above, each Clock component sets up its own timer and updates independently.
In React applications, whether a component is stateful or stateless is considered an implementation detail that can change over time.
We can use stateless components inside stateful components, and vice versa.