Nosa Obaseki Front-end Dev currently building amazing products @theflutterwave 🐼🇳🇬

An Imperative Guide to setState in React

3 min read 959

States in React, like props, are objects that are used to store data and affect how the component renders or behaves. Unlike props, states are managed completely within the component and can be changed over time.

The change in state for React components can be a result of triggers from user actions, network activity, API requests or specific application behavior.

Components that have a state are referred to as stateful components while those that do not have states are referred to as stateless components.

A component can have an initial state set, access it and also update it:

No Title

No Description

 

In the above code block, we are setting the component’s initial state. This is done through the constructor method.

As mentioned previously, states are plain Javascript objects which is why this.state should be equal to an object:

this.state = {
  fruits: ['apple', 'orange'],
  count: 0
}

Accessing component states

Component states can be accessed like other objects using this.state.property_name.

To access the count in the above example, we can do this by this.state.count :

No Title

No Description

Updating component states

Although it is technically possible to write to this.state from anywhere in your code, it’ll not prompt a re-render, and this would lead to unstable and incorrect state values when you try to access the values through this.state.

The only place you should directly write to this.state is the component’s constructor method.

Use thesetState() method everywhere else, doing so will accept an object that will eventually be merged into the component’s existing state.

For example, this will not re-render a component:

No Title

No Description

Instead, use setState().

Introducing setState()

setState() schedule changes to the component’s state object and tells React that this component and its children need to be re-rendered with the update state:

No Title

No Description

React intentionally “waits” until all components call setState() in their event handlers before starting to re-render. This boosts performance by avoiding unnecessary re-renders.

Know that setState() can be considered as a request instead of an immediate command to update the component.

This is why trying to use this.state immediately after a setState() would lead to
incorrect behaviors:

No Title

No Description

this.state.count returns 0 because even though the value has been set with setState(), it was only scheduled and yet to be re-rendered before attempting to use the value with this.state.

setState() will always lead to a re-render unless shouldComponentUpdate() returns false.

Using setState() in React lifecycle methods

Calling setState() in React’s lifecycle methods requires a certain level of caution. There are a few methods where calling setState() would lead to undesirable results and others where it should be avoided completely.

render()

Calling setState() here makes your component a contender for producing infinite loops.

The render() function should be pure, meaning that it does not modify component state, it returns the same result each time it’s invoked, and it does not directly interact with the browser.

In this case, avoid using setState() here.

constructor()

You should not call setState() in the constructor(). Instead, if your component needs to use local state, assign the initial state to this.state directly in the constructor.

componentDidMount()

componentDidMount() is invoked immediately after a component is mounted. You may call setState() immediately in componentDidMount(). It will trigger an extra rendering, but it will happen before the browser updates the screen thus render() will be called twice.

componentDidUpdate()

componentDidUpdate() is invoked immediately after updating occurs. You may call setState() immediately here but know that it must be wrapped in a condition like in the example below, or you’ll cause an infinite loop:

No Title

No Description

componentWillUnmount()

You should not call setState() here because the component will never be re-rendered. Once a component instance is unmounted, it will never be mounted again.

Conclusion

  1. setState() is async, meaning there is no guarantee that the state has been updated if we try to access the value immediately
  2. You can only change state with setState and React will react to the change 😉
  3. Avoid confusing the state object with other instance properties. It’s easy to assume you can define another object in the
    constructor and try to use it like state but the state instance is a special one because React will manage it:

No Title

No Description

Although both this.state and this.user are objects initialized in the
constructor, only this.state reacts with setState() and is managed by React.

Cheers!!!

Plug: LogRocket, a DVR for web apps

LogRocket is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single page apps.

Try it for free.

Nosa Obaseki Front-end Dev currently building amazing products @theflutterwave 🐼🇳🇬

Leave a Reply