Frontend Development 8 min read

Understanding React 18 Tearing: Why Concurrent Rendering Can Show Inconsistent UI

This article explains the concept of UI tearing in React, how synchronous rendering avoids it, why concurrent rendering can introduce visual inconsistencies, and illustrates the phenomenon with diagrams and code examples for developers.

KooFE Frontend Team
KooFE Frontend Team
KooFE Frontend Team
Understanding React 18 Tearing: Why Concurrent Rendering Can Show Inconsistent UI
Original article translated from "What is tearing?"

Overview

Tearing is a traditional term in graphics programming that refers to visual inconsistency.

For example, in video tearing means seeing multiple frames on one screen, making the video look broken. In UI, tearing means the same UI shows multiple values for the same state, such as different prices for the same item in a list.

Because JavaScript is single‑threaded, this problem rarely appears in typical web development. However, React 18’s concurrent rendering can introduce tearing because rendering may be interrupted. When using

startTransition

,

Suspense

, or other concurrent features, React can pause rendering, and updates that occur during the pause may change the data used for rendering, causing the UI to display two different values for the same piece of data.

This is an inevitable result of concurrency. If you want to pause rendering to respond to user input for faster interaction, the data being rendered can change, which may lead to UI tearing.

@flarnie once explained this issue in a talk; this article gives a brief overview and introduces synchronous and concurrent rendering.

Synchronous Rendering

Consider the diagram below.

In the first frame we start rendering the React tree. The component reads a color value from an external store, which is blue, so the component renders blue.

Because we are not using concurrent rendering, React continues rendering all components without interruption. The external store does not change during this time, so every component reads the same value.

In the third frame all components are rendered blue and look identical. The UI state is consistent because every component received the same value.

Finally, the external store can be updated after React finishes rendering, allowing other work to run. If the store changes before the next render, the next render will start again from the first frame and all components will again receive the same value.

This explains why, before concurrent rendering and in most UI frameworks, rendering is always consistent. This is how React 17 works; React 18 does not enable concurrent features by default, so it behaves the same way.

Concurrent Rendering

In most cases the UI produced by concurrent rendering is consistent, but under certain edge conditions tearing can occur. See the diagram below.

The first frame is the same as before: the component renders blue.

From this point the behavior diverges.

Because concurrent features allow React to pause rendering before it finishes, the UI can remain responsive. Suppose a user clicks a button that changes the store’s color from blue to red. In a non‑concurrent render the UI would freeze; in a concurrent render React can let the click be processed, giving a smooth experience.

This pause means that external state can change while rendering is incomplete, so some components may read the new red value while earlier components already rendered blue. This is the edge case that leads to tearing.

In the second frame React has paused, and the external store has changed to red.

In the third frame the first component remains blue (it already read the old value), while later components read the new red value.

In the final frame we see a mix of blue and red components even though they all read from the same store—this visual inconsistency is tearing.

Translator’s note: Developers often mistake rendering issues caused by useEffect or useLayoutEffect for tearing. Tearing usually occurs because React reads external state that changes during concurrent rendering. The example sandbox demonstrates a Redux‑like setup where tearing appears. This article only explains why tearing happens; see the React 18 discussion for mitigation strategies.
frontendJavaScriptReactConcurrent RenderingUI Tearing
KooFE Frontend Team
Written by

KooFE Frontend Team

Follow the latest frontend updates

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.