Categories
React

How to Reduce the Number of Re-renders When Updating States?

Spread the love

Whenever a state is updated in a React component, a re-rendering is done.

This means when we update many states, then there will be lots of re-rendering done.

In this article, we’ll look at how to reduce the number of re-renders in our React components.

How to Reduce the Number of Re-renderings?

We can reduce the number of re-renderings done by reducing the number of states that are updated.

For instance, we can update one object instead state instead of multiple states.

To do this, we write:

import { useEffect, useState } from "react";

export default function App() {
  const [request, setRequest] = useState({
    loading: false,
    data: undefined
  });

  const getData = async () => {
    setRequest((request) => ({ ...request, loading: true }));
    const res = await fetch("https://yesno.wtf/api/");
    const data = await res.json();
    setRequest((request) => ({ ...request, data }));
  };

  useEffect(() => {
    getData();
  }, []);

  useEffect(() => {
    if (request.data) {
      setRequest((request) => ({ ...request, loading: false }));
    }
  }, [request]);

  return <div className="App">{JSON.stringify(request)}</div>;
}

We have the request state which has the loading and data properties.

In the getData function, we call setRequest to update the request state object’s loading property by passing in a callback and returning a new object that’s a copy of request , but loading is set to true .

At the end of the function, we call setRequest again with the new value of data .

Also, we have a useEffect callback that checks is request.data is set and call setRequest with a callback that returns a copy of the request object with loading set to false .

Another way to do this is to create our own hook to merge different state object properties together.

For instance, we can write:

import { useEffect, useState } from "react";

const useMergeState = (initialState) => {
  const [state, setState] = useState(initialState);
  const setMergedState = (newState) =>
    setState((prevState) => ({ ...prevState, newState }));
  return [state, setMergedState];
};

export default function App() {
  const [request, setRequest] = useMergeState({
    loading: false,
    data: undefined
  });

  const getData = async () => {
    setRequest({ loading: true });
    const res = await fetch("https://yesno.wtf/api/");
    const data = await res.json();
    setRequest({ data });
  };

  useEffect(() => {
    getData();
  }, []);

  useEffect(() => {
    if (request.data) {
      setRequest({ loading: false });
    }
  }, [request, setRequest]);

return <div className="App">{JSON.stringify(request)}</div>;
}

We created the useMergeState hook which has the setMergedState function that calls the setState function to merge newState into prevState with the callback in setState .

Then we call useMergeState in App to return our state and state setter function.

Now instead of passing in a callback to the state setter function to merge the state, we just pass in the properties that we want to change to setRequest to change the property.

In either example, we update what we need in our object all at once instead of updating multiple primitive values.

Conclusion

We can reduce the number of re-renders to components with React and JavaScript by putting states into objects and updating them all at once.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

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