React Compiler: Rules of React
React Compiler relies on components and hooks following React’s semantic rules so it can optimize code without changing its behavior. The key ideas are purity, consistent hook usage, and keeping React-specific values and APIs within their intended boundaries.
React components and hooks are expected to behave predictably during rendering. In particular, render logic should be pure: given the same inputs and relevant state, it should not perform arbitrary side effects or mutate values that React or other code may still rely on.
Hooks must follow their usage rules. A hook should be called only from a React component or another hook, and hook calls should occur in the same order on every render rather than being placed inside conditions, loops, or ordinary nested functions. This lets React associate hook state with the correct call position.
The compiler uses these guarantees when transforming component code. If code violates the assumptions, an optimization could otherwise change observable behavior. Compiler diagnostics can identify code that does not satisfy the relevant rules, allowing developers to fix the code or keep affected code outside compiler optimization as appropriate.
Purity does not mean a component can never cause side effects. Effects, event handlers, and other explicitly designed mechanisms are where side effects belong; the important distinction is that the render phase itself should remain free of unintended side effects. This separation gives React and its compiler freedom to re-run, defer, or otherwise transform rendering work.
Key points
- Keep render logic pure and avoid unintended side effects during rendering.
- Call hooks only from React components or custom hooks.
- Do not conditionally call hooks, because React relies on stable hook ordering.
- Avoid mutating props, state, or other values that React may treat as immutable inputs.
- Compiler transformations depend on these semantic guarantees; violations can make optimization unsafe.
Interview questions
Why does React require components to be pure?
React needs rendering to be predictable because it may evaluate a component more than once or at different times. A pure render produces the same UI result from the same inputs without performing unrelated side effects. This lets React safely manage and optimize rendering work. Side effects should instead happen in event handlers or effect mechanisms designed for them.
Why can't hooks be called conditionally?
React associates hook state with the order in which hooks are called during a component render. If a conditional changes that order between renders, a later hook can receive the state belonging to a different hook position. Keeping hook calls unconditional preserves that stable ordering. This is why hooks should be called at the top level of components or custom hooks.
How do the Rules of React relate to the React Compiler?
The compiler makes transformations based on assumptions about React code. Purity, stable hook usage, and appropriate handling of React values give the compiler a reliable semantic model of the program. When code violates those assumptions, transforming it automatically could alter behavior. Compiler diagnostics can therefore surface code that needs correction or should not receive a particular optimization.
Does render purity mean components cannot perform any side effects?
No. The requirement is that the render phase itself remains free of unintended side effects. React provides other mechanisms, such as event handlers and effects, for operations whose purpose is to cause external changes. Separating those operations from rendering preserves the ability to re-run or transform render work. The distinction is therefore about when and where the side effect occurs, not about banning side effects from the application.
What should you do if existing code violates a rule used by the React Compiler?
First identify the specific semantic violation rather than disabling optimization indiscriminately. Refactor the code when practical, such as moving a side effect out of render or restructuring a conditional hook usage. Compiler diagnostics can help locate problematic components or hooks. If a legacy case cannot immediately be changed, the affected code can be handled according to the compiler's supported opt-out or compatibility mechanisms while the broader codebase is improved.