Juan Cruz Martinez I'm an entrepreneur, developer, author, speaker, YouTuber, and doer of things.

How and when to force a React component to re-render

4 min read 1255

React Logo

React usually automatically re-renders components, but for us to truly understand how and when to force React to re-render a component, we need to understand the inner workings of React.

Since the beginning of the web, we’ve used HTML and CSS to define the visual representation of a website. This has not changed, but, with the introduction of JavaScript, new concepts that enable us to read and update the rendered HTML of a page. We call this API DOM.

Libraries like jQuery became extremely popular because they provide an abstraction layer on top of the DOM API that provides enhanced functionality and compatibility, making it easy for developers to build web applications.

But jQuery has its limitations. It doesn’t solve crucial problems developers have when working with dynamically loaded content, such as keeping the JavaScript state (variables) and the DOM (HTML) in sync. Changing a variable in JavaScript does not affect the DOM directly.

Using a framework like React can solve this problem. React relies on JavaScript to maintain the state of an application. This master state object that contains a JavaScript reference to each object on the page is called Virtual DOM. Any changes on virtual DOM reflect automatically on the DOM, and that’s React’s best magic trick.

But how do we update the virtual DOM? We do this by building components and working with state and props.

The next question you may have is, what happens on the edge cases when a component is not updating as expected? Is it even possible? Maybe, but it’s complicated, so let’s discuss it.

Why aren’t React components re-rendering?

Generally, forcing a React component re-render isn’t best practice, even when React fails to update the components automatically. So, before considering forcing a re-render, we should analyze our code, as React magic depends on us being good hosts.

Incorrectly updated state in React

Let’s build a simple component to demonstrate one common reason components aren’t rendering. We will build a simple app that will show a username, Juan, and, after pressing a button, the name will change to Peter.

Here is a demonstration of the app with the complete code. You probably noticed that after clicking the button, nothing happens, even though we changed our state on the button:

We made a custom demo for .
No really. Click here to check it out.

function changeUserName() {
   user.name = "Peter";
   setUser(user);
 }

The component did not change, so there was no re-rendering trigger. Here’s why.

React evaluates state changes by checking its shallow equality (or reference equality), which checks to see if both the preview and new value for state reference the same object. In our example, we updated one of the properties of the user object, but we technically made setUser the same object reference, and thus, React didn’t perceive any change in its state.

State, as described in the React documentation, should be treated as immutable.

So, how do we fix it? We could create a new object with the correct values as follows:

function changeUserName() {
   setUser({
     ...user,
     name: "Peter"
   });
 }

Note that we are using the spread operator in JavaScript to preserve the properties of the original object while updating its name property under a new object. The final result can be observed here.

Incorrectly updated props without state change

While it may seem impossible, incorrectly updating props without a state change can happen, and it usually leads to bugs. Let’s look at an example.

In this demo, I built a clock that has a major problem: the time doesn’t change after I first load the screen. Not a very useful clock, right?

Let’s take a look at the code responsible for calculating the current time:

let myTime;

 function setMyTime() {
   myTime = new Date();
   setTimeout(() => {
     setMyTime();
   }, 1000);
 }

 setMyTime();

This code looks ugly and is generally not a great way to code for a React component, but it works. Every second, the runtime will call the function setMyTime and will update the variable myTime, which is then passed to our Clock component for rendering.

<Clock myTime={myTime} />

This demo doesn’t work because props are a reflection of state, so a standalone change in props won’t trigger a re-render. To fix it, we need a total rewrite.

Notice that we introduced state to manage myTime and useEffect to start and clear the timers to avoid bugs when the component re-renders. And it works!

const [myTime, setMyTime] = useState(new Date());

 useEffect(() => {
   var timerID = setInterval(() => tick(), 1000);

   return () => clearInterval(timerID);
 });

 function tick() {
   setMyTime(new Date());
 }

Forcing a React component to re-render

It’s typically frowned upon to force a component to re-render, and the failure of automatic re-rendering in React is often due to an underlying bug in our codebase. But, if you have a legitimate need to force a React component to re-render, there are a few ways to do it.

Forcing an update on a React class component

If you are using class components in your code, you’re in luck. React provides an official API to force a re-render, and it’s straightforward to implement:

someMethod() {
   // Force a render without state change...
   this.forceUpdate();
 }

In any user or system event, you can call the method this.forceUpdate(), which will cause render() to be called on the component, skipping shouldComponentUpdate(), and thus, forcing React to re-evaluate the Virtual DOM and DOM state.

There are some caveats to this method:

  • React will trigger the normal lifecycle methods for child components, including shouldComponentUpdate(), so we only can force the current component to be re-rendered
  • VirtualDOM will still validate its state with DOM, so React will only update the DOM if the markup changes

Forcing an update on a function component

There’s no official API to re-render a function component, nor is there a React Hook. There are, however, some clever tricks to signal to React that a component should be updated.

  1. Replace state objects with a new instance of themselves

Let’s say we want to force a refresh on our change user example above. We could do something like this:

someMethod() {
   // Force a render with a simulated state change
   setUser({ ...user });
 }

Because user is an object, we could copy it to a new object and set it as the new state. The same could apply to any other object or array.

2. Have an empty state variable trigger updates

This method is interesting, as it creates a new object in the state. We only care about its update function as follows:

const [, updateState] = React.useState();
const forceUpdate = React.useCallback(() => updateState({}), []);

Here, we use useCallback to memoize our forceUpdate function, thus keeping it constant throughout the component lifecycle and making it safe to be passed to child components as props.

Here is an example of how to use it:

import React from "react";

export default function App() {
 const [, updateState] = React.useState();
 const forceUpdate = React.useCallback(() => updateState({}), []);

 console.log("rendering...");

 return (
   <div className="App">
     <h1>Time to force some updates</h1>
     <button onClick={forceUpdate}>Force re-render</button>
   </div>
 );
}

Now, each time we click on the Force Re-render button, the component will re-render. You can access the live demo here.

Conclusion

In general, we should prevent forcing React to re-render components. If React fails to do re-render components automatically, it’s likely that an underlying issue in your project is preventing the components from updating correctly.

However, we covered a few common ways to force React to re-render components should it be required. Happy coding!

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

Juan Cruz Martinez I'm an entrepreneur, developer, author, speaker, YouTuber, and doer of things.

Testing accessibility with Storybook

One big challenge when building a component library is prioritizing accessibility. Accessibility is usually seen as one of those “nice-to-have” features, and unfortunately, we’re...
Laura Carballo
4 min read

Leave a Reply