The React Compiler enforces rules that have always been part of React's mental model. Understanding these rules is crucial for writing correct React code.
Rule 1: Components and Hooks Must Be Pure
During rendering, components should only:
- Read props, state, and context
- Return JSX
tsx// ❌ Side effects during render function BadComponent() { document.title = 'Updated!'; // Side effect! localStorage.setItem('key', 'value'); // Side effect! return <div>Content</div>; } // ✅ Side effects in event handlers or effects function GoodComponent() { useEffect(() => { document.title = 'Updated!'; }, []); const handleClick = () => { localStorage.setItem('key', 'value'); }; return <button onClick={handleClick}>Save</button>; }
Rule 2: React Calls Components and Hooks
Don't call components as functions or hooks outside components:
tsx// ❌ Calling component as function function Parent() { const result = Child(); // Wrong! return <div>{result}</div>; } // ✅ Rendering as JSX function Parent() { return <div><Child /></div>; } // ❌ Calling hooks outside components const value = useState(0); // Wrong! // ✅ Hooks inside components function Component() { const [value, setValue] = useState(0); }
Rule 3: Rules of Hooks
Hooks must be called:
- At the top level of components
- Not inside conditions, loops, or nested functions
tsx// ❌ Conditional hook function Component({ condition }) { if (condition) { const [state, setState] = useState(0); // Wrong! } } // ✅ Unconditional hook, conditional usage function Component({ condition }) { const [state, setState] = useState(0); if (condition) { // Use state here } }
Rule 4: Only Call Hooks from React Functions
Hooks can only be called from:
- Function components
- Custom hooks
tsx// ❌ Hook in regular function function helper() { const [state, setState] = useState(0); // Wrong! } // ✅ Hook in custom hook function useHelper() { const [state, setState] = useState(0); // Correct! return state; }
Why These Rules Matter
1. Predictable Rendering
React may render components multiple times, skip renders, or render in different orders. Pure components work correctly regardless.
2. Concurrent Features
React's concurrent features (Suspense, transitions) rely on being able to pause and resume rendering. Side effects during render break this.
3. Compiler Optimization
The React Compiler assumes these rules are followed. Violations can cause incorrect optimizations.
Detecting Violations
Strict Mode
tsx<StrictMode> <App /> </StrictMode>
Strict Mode helps detect:
- Impure renders (by rendering twice)
- Missing effect cleanup
- Deprecated APIs
ESLint Rules
js{ "extends": [ "plugin:react-hooks/recommended" ] }
Catches:
- Hooks called conditionally
- Missing dependencies
- Invalid hook calls