MWAN MOBILE

×
mwan_logo
blog-banner

Why React doesn’t update state immediately

Application Development 09-Oct-2023

Despite React’s popularity, one of its biggest drawbacks is its components re-rendering excessively. When developing React applications, you may have noticed that state updates don’t immediately reflect new values after being changed. React state is a plain JavaScript object that holds information that influences the output of a render.

When building your project, if you intend to alter any attributes of a React component in the future, you should store the attribute in a state. The state starts with an initial default value on mount and is then altered later on as a result of a user’s actions. Each React component manages its own state internally.

In this article, we’ll explore the reasons why React doesn’t update state immediately. We’ll run through an example and clarify what you should do when you need to make changes to the new state in both class and function components. Let’s get started!

How React performs state updates

To update state in React components, we’ll use either the this.setState function or the updater function returned by the React.useState() Hook in class and function components, respectively.

State updates in React are asynchronous; when an update is requested, there is no guarantee that the updates will be made immediately. The updater functions enqueue changes to the component state, but React may delay the changes, updating several components in a single pass.

For example, consider the code below:

//React
const handleClick = () => {
      setName("Amaka")
      setAge(20)
      setAddress("No 3 Rodeo drive")
}

In the code snippet above, there are three different calls to update and re-render the component. Calling the updater functions one after another and re-rendering both parent and child components after each call would be inefficient in most cases. For this reason, React batches state updates.

No matter how many setState() calls are in the handleClick event handler, they will produce only a single re-render at the end of the event, which is crucial for maintaining good performance in large applications. The order of requests for updates is always respected; React will always treat the first update requests first.

Now that we’ve established that delaying reconciliation of updates requests in order to batch them is beneficial, there are also times when you need to wait on the updates to do something with the updated values. In the next section, we’ll see how to do that.

Carrying out operations with class components

setState() callback

The second parameter to setState() is an optional callback function. This argument will be executed once setState() is completed and the component is re-rendered. The callback function is guaranteed to run after the state update has been applied:

//React

handleSearch  = (e) => {
    this.setState({
    searchTerm: e.target.value
  },() => {
    // Do an API call with this.state.searchTerm
  });
}

componentDidUpdate

The componentDidUpdate function is invoked immediately after a state update occurs. To avoid an infinite loop, you should always use a conditional statement to be sure that the previous state and the current state are not the same:

//React

componentDidUpdate(prevProps, prevState) {
  if (prevState.count !== this.state.count) {
    // Do something here
  }
}

Carrying out operations with function components

useEffect() Hook

You can perform side effects in the useEffect Hook when the state is updated. The state variable could be added as a dependency in this Hook, making it run when the state value changes. You can make the useEffect Hook listen to the state changes:

//React

import React,{useState, useEffect} from 'react';

const App = () => {
  const [count, setCount] = useState(1);

  useEffect(() => {
    if (count > 5) {
      console.log('Count is more that 5');
    } else {
      console.log('Count is less that 5');
    }
  }, [count]);

  const handleClick = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>{count}</p>

      <button onClick={handleClick}>
        add
      </button>
    </div>
  );
};

export default App;

The callback function in the useEffect Hook runs only when the state variable provided as a dependency changes.

Conclusion

In React, every state update causes the component being updated to re-render. Because re-rendering is an expensive operation, making state updates synchronously can cause serious performance issues, for example, increasing load times or causing your application to crash. By batching state updates, React avoids unnecessary re-renders, boosting performance overall. I hope you enjoyed this article!

Get set up with LogRocket’s modern React error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID.
  2. Install LogRocket via NPM or script tag. LogRocket.init() must be called client-side, not server-side.
  3. NPM
  4. Script Tag
  5. (Optional) Install plugins for deeper integrations with your stack:
    • Redux middleware
    • ngrx middleware
    • Vuex plugin

Source: LogRocket