React – State

A state is a piece of data maintained by a component for itself and has full control over it.

Imagine a switch. It can be in one of the two states: “on” or “off.” A component can have multiple states that keep track of user actions and maintain the changes.

Need For State in React

Applications need to be interactive. For that, components should be able to respond to user interactions. State stores the data that may change over time. Props are fixed and cannot be changed.

This is how a typical component gets the data (state, props) and generates the UI(User Interface):

Props are external and immutable, but the component can change the state as it belongs internally. Events like button clicks, form submits are used to perform state changes.

React keeps the UI and the data always in sync. Any data change is automatically reflected in the UI.

Rules of State in React

  • Every single component maintains its independent copy of the state (if any).
  • Any change made to a component’s state triggers the update cycle and re-renders that component and its children.
  • The state can be passed to other components as props.
  • The state can be updated only by the component that owns/defines it.

State in Class Components

Class Components have full support for using state and its features. The first step to using a state inside a component is to define it.

Defining a State

The state must be defined inside the constructor function of a class component. To define the state, we have to assign an object literal in the this.state property.

The code below defines two state properties: counts and hides with their default values.

class MyComponent extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            count: 0,
            hide: false
        }
    }
    // render function…
}

The above component will have the default state values when it is first mounted to the DOM.

Using a State

Since the state is defined in this.state property, it is also accessed (read) through this.state object.

So, from the previous code, we can access the count and hide property through this.state.count and this.state.hide. Now if we need to use count and hide in our component, we will have to update our render method.

render() {
    return ( <div>
          <h1> {
            this.state.count
        } </h1> 
            <p> Hide: {
            String(this.state.hide)
        } </p> 
            </div>
    )
}

Updating a State

Remember that props cannot be updated, but states can. React provides a method called this.setState() that you can use to update the component’s state. You need to pass an object with the changed state value to it.

Updating a State is most commonly done on user interaction like button click, form submits, etc. Let’s add a button to the previous code that will be able to increment the count value.

// … code before …
<div>
      <h1> Count: {
        this.state.count
    } </h1> 
       <p> Hide: {
        String(this.state.hide)
    }  </p> 
     <button onClick = {
        () => this.setState({
            count: this.state.count + 1
        })
    } >
    Increment Count 
     </button> 
</div>
// … code after …

Once the button “Add Count” is clicked,  the component updates the count value and displays it accordingly.

The DOM update is automatically managed by React more efficiently. You need to worry about how and when to do state updates. We can sum up the definition, usage, and updates as in the chart below.

The SetState() method

The setState() method is used to update a component’s state. The state must never be updated directly by overwriting this.state, such as this.state.count = 10

Doing so will not re-render the component, and the changes will not be reflected.

The setState() has two forms:

1st Form – this.setState(newState)

this.setState(newState)

You can pass a part of the state to update and it will be merged with the existing state. Example: If you had a previous state as:

this.state = {
    count: 5,
    hide: false,
    status: 'active'
}

Then on running this.setState({ count: 10 }) the previous state will be updated to:

this.state = {
    count: 10,
    hide: false,
    status: 'active'
}

Updates are done only on the matching properties. The existing state values are not modified or removed.

Since the setState() method is asynchronous, so any code that you want to synchronously run after the state update must be put inside a callback function.

this.setState(updatedState, () => {
    // … do something once state has updated.
})

2nd Form – this.setState((state, props) => newState)

You can also pass a function to this.setState() as the first parameter instead of an object. The callback function receives two parameters: current state and props. And it should return an updated state object.

We should use this form of setState() to access the previous state for updating it.

/* Always use this form if you want to use the previous state to derive the new state: */
this.setState(
(state, props) => ({ count: state.count + 1, status: 'inactive' })
)
/* avoid updates like like this */
this.setState({ count: this.state.count + 1, status: 'inactive' })

Using State in Functional Components

Functional components don’t have a state. But using React Hooks (special react functions), we can use state even inside them, by using a hook called useState() that returns an array with two elements. The first element is the state and the second is a function that is used for updating the state.

So, if we want to store a name, then we can do something like this:

const [name, setName] = useState('John')

Now, “name” is a state with the initial value ‘John’. To update the “name”, call setName('Updated Name'). You can see the similarities of using state in class and functional components in the chart below.

To use multiple states, we can declare useState() as many times as we want. We can rewrite the previous example using functional components as below:

import {
    useState
} from 'react'
function MyComponent() {
    const [count, setCount] = useState(0)
    const [hide, setHide] = useState(false)
    const [status, setStatus] = useState('active')
    return (
       <div>
        <h1> {
            count
        } </h1> 
           <p> Hide: {
            String(hide)
        }  </p> 
         <button onClick = {
            () => setCount({
                count: count + 1
            })
        }>
        Increment Count 
         </button> 
        </div>
    )
}

Conclusion

The state is a very fundamental concept of React and is used in almost all components. We need to remember that using “state” in class components and functional components is different, but the idea is the same.

The state helps a component to be interactive and do something whenever it is changed.

Back to: React Tutorial > Learn React

Leave a Reply

Your email address will not be published. Required fields are marked *