In English, state refers to "the particular condition that someone or something is in at a specific time" and that holds true in React as well. State is basically a JavaScript object that stores a component's data that are prone to changes, enabling a component to keep track of the changing information in between renders. That's what makes components reactive in nature.
The Why
If you have a static app, don't use state. However, if you want your app to be interactive, like for example a clock widget that shows and updates time at a set interval or an app where one can log in and out, add, delete and update resources - it will involve state.
But, wait a minute don't we use props to store data in components? Yes, but the crucial difference here is that props are immutable (read-only) in that the components can not change their props as they are passed down from parent components. In contrast, component has a full control over its state and can modify it.
The How
Let's look at an example (inspired by the ticking clock example in React docs) to see how state works.
We will build a simple Countdown
component that renders the final countdown to the New Year's day.
Keep in mind,
state is a feature only available in classes
So, let's start by building an ES6 class for our component and write some pseudo code inside to show what it should do.
import React from 'react'
import ReactDOM from 'react-dom';
export default class Countdown extends React.Component {
timer () {
// some function that updates the countdown
}
render () {
return (
// shows the countdown 10 through 1 and renders the message HAPPY NEW YEAR!!
)
}
}
const element = <Countdown />
ReactDOM.render(element, document.getElementById('root'));
Now, in order to manipulate the state, you ought to have something to begin with, right? Yup, an initial state. So, let's do that - let's declare the initial state of the component and give it an attribute of secondsLeft
. We'll start with 10 secondsLeft
and do a countdown until it's 0 secondsLeft
. Now, where shall we declare the initial state? Constructor function it is! Because that's what fires before our component is mounted, making it the perfect candidate for setting up defaults including the initial state. Let's add the following block inside our component class.
constructor() {
super();
this.state = { secondsLeft: 10}
}
Make sure to pass in
props
as an argument toconstructor()
andsuper()
if you wish to usethis.props
within the class.
Now, let's work on our timer()
function that updates our component's state of secondsLeft
by subtracting 1 from it.
timer = () => {
if (this.state.secondsLeft > 0) {
this.setState({ secondsLeft: this.state.secondsLeft - 1 })
}
}
We use
this.setState()
to update a component's state rather than doing something likethis.state = someValue
Calling this.setState()
tells React that the component's state has updated and that the component needs to be re-rendered.
Also, notice that I used an arrow function to define timer
. This is to bind the keyword this
to the instance of the component we are working with.
Moving on, let's add a lifecycle method componentDidMount()
which will run after the component output has been rendered in the DOM. This is also a good place to call timer()
. So, starting with the initial state, with every second the state of the component updates as timer()
fires, thus re-rendering the component every second.
componentDidMount() {
setInterval(
() => this.timer(),
1000
);
}
Here's the final code:
import React from 'react';
import ReactDOM from 'react-dom';
export default class Countdown extends React.Component {
constructor() {
super();
this.state = { secondsLeft: 10 }
}
componentDidMount() {
setInterval(
() => this.timer(),
1000
);
}
timer = () => {
if (this.state.secondsLeft > 0) {
this.setState({ secondsLeft: this.state.secondsLeft - 1 })
}
}
render() {
const message = (this.state.secondsLeft === 0 )? <font color="red">Happy New Year!!!</font> : this.state.secondsLeft
return <h1>{ message }</h1>
}
}
const el = <Countdown />
ReactDOM.render(el, document.getElementById('root'));
...aaaaand Action!!
TL;DR
- If you want interactive components use state
- State is a feature only available within class components
- React maintains state as an object which can be accessed through
this.state
- State is similar to props, but is private and fully controlled by the component and can not be accessed and modified outside the component (think encapsulation)
- Don't set the state directly like
this.state = someValue
but usethis.setState()
instead
Top comments (4)
With hooks it's possible to have state in functional components nowdays.
Great, i'll have to look into that :)
Thanks for this! Great write-up and it was the first time I've ever been able to say: "Wait, I already know something about React!".
Right on! I'm glad you found the post useful :)