This project demonstrates how React Compiler automatically optimizes React components without the need for manual optimizations like memo, useMemo, and useCallback.
The demo is automatically deployed to GitHub Pages on every push to the main branch.
|
β Good Examples |
β Bad Examples |
This demo accompanies the blog post: 9 bΕΔdΓ³w, ktΓ³re zablokujΔ React Compiler i jak wykrywa je ESLint
Read the article to learn more about common mistakes that prevent React Compiler from optimizing your code.
- Components without
React.memo() - Functions without
useCallback() - Calculations without
useMemo() - All automatically optimized by React Compiler!
Examples of code that violates Rules of React and triggers ESLint errors:
- Conditional Hook Calls - Calling hooks conditionally
- Props Mutation - Mutating component props
- Side Effects During Render - Side effects outside useEffect
- Direct State Mutation - Mutating state directly
- Hook Inside a Loop - Calling hooks in loops
- Hook Inside Nested Function - Calling hooks in nested functions
- Missing Effect Dependencies - useEffect with missing dependencies
- Component Defined Inside Render - Unstable component definition
- Mutating Hook Values - Mutating reactive values from hooks
yarn install
yarn devOpen your browser and navigate to the local development server (usually http://localhost:5173).
The project uses the latest ESLint configuration with react-hooks rules to detect Rules of React violations:
// eslint.config.js
import js from "@eslint/js";
import globals from "globals";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";
import { defineConfig, globalIgnores } from "eslint/config";
export default defineConfig([
globalIgnores(["dist"]),
{
files: ["**/*.{ts,tsx}"],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs.flat["recommended-latest"],
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
rules: {
"react-hooks/exhaustive-deps": "error",
},
},
]);Run ESLint to see all Rules of React violations:
yarn lintBuild the project to see React Compiler optimizations:
yarn build- β Conditional hook calls (react-hooks/rules-of-hooks)
React Hook "useState" is called conditionally - β Hooks in loops (react-hooks/rules-of-hooks)
React Hook "useState" may be executed more than once - β Hooks in nested functions (react-hooks/rules-of-hooks)
React Hook "useState" cannot be called inside a callback - β Component defined inside render (react-hooks/rules-of-hooks)
React Hook "useState" cannot be called in a function component body - β Missing effect dependencies (react-hooks/exhaustive-deps)
React Hook useEffect has a missing dependency: 'value'
Note: Some violations like props/state mutations may require additional ESLint plugins to detect, but React Compiler will handle them at compile time.
React Compiler automatically:
- β
Memoizes components (no need for
React.memo) - β
Memoizes values (no need for
useMemo) - β
Memoizes functions (no need for
useCallback) - β Optimizes re-rendering without manual intervention
- β Detects Rules of React violations at compile time
Note: This may impact Vite dev & build performance, but the runtime performance will be significantly better.
- React 19.2.0
- TypeScript 5.9.3
- Vite 7.3.1
- Tailwind CSS 4.2.1
- babel-plugin-react-compiler 1.0.0
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [
tailwindcss(),
react({
babel: {
plugins: [['babel-plugin-react-compiler']],
},
}),
],
})import js from "@eslint/js";
import globals from "globals";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";
import { defineConfig, globalIgnores } from "eslint/config";
export default defineConfig([
globalIgnores(["dist"]),
{
files: ["**/*.{ts,tsx}"],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs.flat["recommended-latest"],
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
rules: {
"react-hooks/exhaustive-deps": "error",
},
},
]);Use the tab navigation at the top to switch between:
- β Good Examples - Properly optimized code with React Compiler
- β Bad Examples - Rules of React violations with ESLint errors
The navigation is sticky at the top, so it remains accessible as you scroll through the content.
Open src/BadExamples.tsx in your IDE to see:
- Red underlines on problematic code
- Hover over errors to see detailed messages
- ESLint will show exactly what Rules of React are violated
Example errors you'll see:
β Issue 1: Conditional hook calls (react-hooks/rules-of-hooks)
β Issue 2: Mutating props directly
β Issue 3: Side effects during render (use useEffect instead)
β Issue 4: Mutating state directly
β Issue 5: Hooks inside loops (react-hooks/rules-of-hooks)
β Issue 6: Hooks inside nested functions (react-hooks/rules-of-hooks)
β Issue 7: Missing useEffect dependencies (react-hooks/exhaustive-deps)
β Issue 8: Component defined inside render (react-hooks/rules-of-hooks)
β Issue 9: Mutating reactive values from hooks
Note: The ESLint errors in BadExamples.tsx are intentional to demonstrate what React Compiler detects and prevents!
src/
βββ App.tsx # Main app with tab navigation
βββ GoodExamples.tsx # β
Good examples (optimized by React Compiler)
βββ BadExamples.tsx # β Bad examples (Rules of React violations)
βββ main.tsx # Entry point
βββ index.css # Global styles
- React Compiler works transparently - you won't see special badges in React DevTools. The optimizations happen at compile time.
- ESLint is your friend - The
react-hooksrules will catch code that violates Rules of React and may prevent React Compiler from optimizing properly. - Write clean React code - Follow the Rules of React, and React Compiler will automatically optimize your components without manual
memo,useMemo, oruseCallback. - The errors in
BadExamples.tsxare intentional - they serve as educational examples of what NOT to do.
- Start by exploring
GoodExamples.tsxto see properly written React code - Click "Bad Examples" tab to see common mistakes
- Open
BadExamples.tsxin your IDE to see ESLint errors - Run
yarn lintto see all violations in the terminal - Compare the two approaches to understand React Compiler requirements
Rule violated: react-hooks/rules-of-hooks
Hooks must be called in the exact same order on every render. Calling hooks conditionally breaks this rule.
// β BAD
if (showCount) {
const [count] = useState(0); // Hook called conditionally!
}
// β
GOOD
const [count] = useState(0);
if (showCount) {
return <div>Count: {count}</div>;
}Rule violated: Immutability
Props are read-only. Mutating them directly violates React's immutability principle.
// β BAD
data.value = 100; // Never mutate props!
// β
GOOD
const newData = { ...data, value: 100 };Rule violated: Component purity
Components should be pure functions. Side effects should be in useEffect.
// β BAD
externalStore.data["key"] = value; // Side effect during render!
// β
GOOD
useEffect(() => {
externalStore.data["key"] = value;
}, [value]);Rule violated: State immutability
State must be treated as immutable. Always create a new object/array when updating.
// β BAD
user.age = 26;
setUser(user); // Won't trigger re-render properly
// β
GOOD
setUser({ ...user, age: 26 });Rule violated: react-hooks/rules-of-hooks
Hooks cannot be called inside loops because the number of hooks must be consistent.
// β BAD
for (let i = 0; i < items.length; i++) {
useState(items[i]); // Hook in a loop!
}
// β
GOOD
const [states, setStates] = useState(items);Rule violated: react-hooks/rules-of-hooks
Hooks must be called at the top level of a component, not inside nested functions.
// β BAD
function createState() {
const [count] = useState(0); // Hook in nested function!
return count;
}
// β
GOOD
const [count] = useState(0);Rule violated: react-hooks/exhaustive-deps
All variables used inside useEffect must be declared in the dependency array.
// β BAD
useEffect(() => {
console.log(value);
}, []); // Missing 'value' in dependencies!
// β
GOOD
useEffect(() => {
console.log(value);
}, [value]);Rule violated: react-hooks/rules-of-hooks
Components should be defined outside of render to avoid recreating them on every render.
// β BAD
const MyComponent = () => {
const InnerComponent = () => { // Defined inside!
return <div>Inner</div>;
};
return <InnerComponent />;
};
// β
GOOD
const InnerComponent = () => {
return <div>Inner</div>;
};
const MyComponent = () => {
return <InnerComponent />;
};Rule violated: Reactive value immutability
Values returned from hooks (like state) should be treated as immutable.
// β BAD
const [config] = useState({ enabled: true });
config.enabled = false; // Mutating reactive value!
// β
GOOD
const [config, setConfig] = useState({ enabled: true });
setConfig({ enabled: false });The project detects these violations using:
react-hooks/rules-of-hooks- Detects Issues 1, 5, 6, 8react-hooks/exhaustive-deps- Detects Issue 7- Component purity and immutability - Issues 2, 3, 4, 9 (detected at compile time by React Compiler)

