Signals Clash with React Compiler
Recent posts raised compatibility concerns between signals-style libraries (Solid, Angular, Preact signals) and the React Compiler, arguing that some signal designs push authors back toward React Context patterns for composition and type safety. The debate highlights that alternative reactivity models can create friction with compiler-driven optimizations and existing JSX conventions. For teams designing internal primitives, that means trade-offs between subscription granularity and predictable static analysis remain unresolved. (x.com)
A React component is usually a recipe that runs top to bottom and returns user interface markup called JavaScript XML, which is the tag-like syntax React turns into elements on the page. The React Compiler is a build-time tool that reads those recipes ahead of time and automatically adds memoization, which means “don’t recalculate this part if the inputs did not change.” (react.dev, react.dev) Signals flip that model around. A signal is a box with a `.value` field, and code that reads that field subscribes to future changes so only the exact readers update later. (preactjs.com, preactjs.com) That sounds cleaner until you put both ideas in the same app. A compiler wants code it can understand by scanning the source once, while a signal system often decides subscriptions at runtime when some branch actually reads `.value`. (react.dev, preactjs.com) The latest flare-up started with posts arguing that this mismatch shows up fastest in shared primitives, not toy counters. When a design system team wants one helper to compose several signals and stay type-safe in TypeScript, some patterns start looking like React Context again, with a provider high in the tree and consumers reading from it below. (x.com, react.dev) React Context is React’s built-in tunnel for passing a value through many component layers without threading it through every prop. React’s own docs describe it as the escape hatch for “prop drilling,” which is the tedious version where every parent has to pass the same value down by hand. (react.dev) That is the irony in this debate. Signals were popular partly because they promised more precise updates than broad tree-wide patterns, but once authors need composition, ownership rules, and types that survive across many files, they can end up rebuilding a central container anyway. (preactjs.com, react.dev) The React side of the argument is straightforward: the compiler only helps when code follows patterns it can prove are safe. The official docs say it understands the Rules of React and can compile libraries too, which means library authors are now being asked to shape abstractions around what static analysis can reliably see. (react.dev, react.dev) The signals side is also straightforward: subscription granularity is real. Preact’s docs pitch signals as values that update only the places that read them, and that can avoid the “rerender the whole branch” feeling developers associate with coarse state propagation. (preactjs.com, preactjs.com) So the fight is not “fast versus slow.” It is “runtime precision versus compile-time predictability,” and those two goals pull library design in different directions when the same JavaScript XML component model has to satisfy both. (react.dev, preactjs.com) React made that tension more visible when React Compiler 1.0 shipped on October 7, 2025 and React’s docs started telling developers the compiler can apply the equivalent of `memo` automatically. Once the framework promises optimization by default, any state model that hides dataflow from the compiler gets judged more harshly. (react.dev, react.dev) That leaves teams building internal state primitives with an awkward choice. They can favor signals-style APIs that give fine-grained subscriptions, or they can favor compiler-friendly APIs that look more like standard React state and context, but today there is no single pattern that cleanly maximizes both. (react.dev, preactjs.com)