tezvyn:

Tearing and useSyncExternalStore in concurrent React

AI-drafted, machine-checkedSource: interviewadvanced
WHAT IT TESTS

Concurrency consistency guarantees.

OUTLINE

Tearing is inconsistent UI when an interruptible render reads a changed external store mid-pass; useSyncExternalStore subscribes and forces consistent snapshots, re-rendering synchronously on change.

WHAT THIS TESTS Whether you understand that concurrent rendering can interrupt and resume a render pass, and why mutable external stores need a dedicated subscription primitive to stay consistent.

A GOOD ANSWER COVERS In React's concurrent model a render is interruptible: React can start rendering, pause, let a higher-priority update run, and resume. If a component reads from an external mutable store, like a Redux-style store or a browser API, and that store changes between the start and end of a single render pass, components rendered before the change show the old value while those rendered after show the new one. That visible inconsistency within one commit is tearing. useSyncExternalStore solves it by taking a subscribe function and a getSnapshot function. React reads the snapshot, and if it detects the store changed during a concurrent render, it bails out and re-renders synchronously so every component reads the same value, guaranteeing a consistent commit. getServerSnapshot supports SSR and hydration.

COMMON WRONG ANSWERS Describing tearing as stale state or a missed re-render; it is intra-render inconsistency. Thinking useState or useEffect subscriptions are equivalent and safe under concurrency. Forgetting getServerSnapshot for SSR. Assuming the store itself can fix this without React cooperation.

LIKELY FOLLOW-UPS Why can't a plain useEffect subscription guarantee no tearing? What does getServerSnapshot prevent during hydration? How do libraries like Redux and Zustand use this hook? What is the cost of the synchronous bail-out?

ONE CONCRETE EXAMPLE A store holds a font-size value used by two sibling panels. Under concurrent rendering React begins a low-priority render, an event bumps the size, and React resumes; without the hook one panel could render at the old size and the other at the new size in the same frame. Wrapping reads in useSyncExternalStore(store.subscribe, store.getSnapshot) makes React detect the change and re-render both panels from one consistent snapshot, so they never disagree on screen.

Read the original → github.com

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.