React Compiler pitfalls

Recent community posts flagged a concrete pitfall for React Compiler compatibility: mutating ref.current during render can break compiler optimizations and destabilize assumptions about render purity. At the same time there’s optimism that the Compiler can play nicely with signals‑style libraries, though seamless integration will depend on careful design around Compiler and Context semantics. That discussion matters for library authors because small implementation choices can block downstream compile‑time optimizations. (x.com) (x.com)

React Compiler is a build tool that tries to make React code faster by automatically remembering work your component already did, the way a browser remembers a page in cache instead of rebuilding it from scratch. React’s own docs describe it as “automatic memoization” for components and values. (react.dev) That only works if render behaves like a calculator: same inputs, same output, no hidden side effects. React’s rules say components and hooks must be pure, because React may run render more than once, pause it, or throw work away before committing it to the screen. (react.dev) A ref is React’s little mutable box, stored as `ref.current`, for values you want to keep without causing a re-render. React’s `useRef` docs say changing `ref.current` does not trigger rendering because a ref is just a plain JavaScript object. (react.dev) The trap is where you touch that box. React’s docs say “Do not write or read `ref.current` during rendering, except for initialization,” because doing that during render makes component behavior unpredictable. (react.dev) That warning is no longer just style advice for people chasing edge-case bugs. The React team’s compiler tooling now ships a `refs` lint specifically to catch unsafe ref reads and writes, and the React Compiler v1.0 post called out “preventing unsafe ref access during render” as one of the checks it recommends enabling. (react.dev 1) (react.dev 2) You can see the compiler’s assumption in public issue threads. In one React repository issue from October 23, 2024, a React team member said that returning `ref.current` from a `usePrevious` hook breaks a Rule of React because any consumer would be accessing the ref during render. (github.com) Another issue shows the practical outcome: the compiler can “deopt,” meaning it gives up on an optimization, when it sees ref access patterns during render. A September 2025 issue describes the compiler bailing out with “Cannot access refs during render” for checks like `!ref.current`. (github.com) This is why a tiny library implementation detail can ripple outward. If a hook hides a render-time ref mutation inside its internals, every app that imports that hook may lose compiler optimizations even if the app code itself looks clean. (react.dev) (github.com) The safer pattern is to treat refs like backstage storage, not part of the script the actor reads on stage. React’s docs say reading and writing refs is fine in event handlers and effects, where React is no longer trying to prove that render is pure. (react.dev 1) (react.dev 2) That is also why people are talking about signals-style libraries in the same breath as the compiler. Preact Signals describes signals as a state system for React and other frameworks, but its React package already has caveats around how tracking works in server rendering, which shows that “works with React” and “fits React Compiler assumptions” are two different bars. (github.com) The likely end state is not “signals good” or “refs bad.” It is that any library that wants React Compiler wins has to preserve React’s purity model during render, avoid hidden mutable reads that the compiler cannot safely reason about, and be careful about how context and subscriptions expose changing values to components. (react.dev 1) (react.dev 2)

Get your own daily briefing

Scout delivers personalized news, insights, and conversations tailored to your role and industry.

Download on the App Store

Shared from Scout - Be the smartest in the room.