[{"data":1,"prerenderedAt":1892},["ShallowReactive",2],{"page-\u002Freact\u002F01-introduction-and-setup":3},{"id":4,"title":5,"body":6,"description":1885,"extension":1886,"meta":1887,"navigation":58,"path":1888,"seo":1889,"stem":1890,"__hash__":1891},"content\u002Freact\u002F01-introduction-and-setup.md","01 — Introduction & Setup",{"type":7,"value":8,"toc":1872},"minimark",[9,13,18,136,140,282,286,384,520,650,654,665,669,949,953,1117,1121,1324,1328,1417,1421,1520,1524,1528,1625,1632,1780,1784,1868],[10,11,5],"h1",{"id":12},"_01-introduction-setup",[14,15,17],"h2",{"id":16},"what-react-actually-is","What React Actually Is",[19,20,23],"code-wrapper",{"filename":21,"language":22},"react_core_model.js","javascript",[24,25,29],"pre",{"className":26,"code":27,"language":22,"meta":28,"style":28},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F React = a declarative, component-based UI library. Not a framework.\n\u002F\u002F No router, no data layer, no state manager. ONE job: keep the UI in sync\n\u002F\u002F with your data via virtual DOM diffing and unidirectional data flow.\n\n\u002F\u002F THE MENTAL MODEL:\n\u002F\u002F   state → render → virtual DOM → diff → commit to real DOM\n\u002F\u002F\n\u002F\u002F You describe WHAT the UI should look like for a given state.\n\u002F\u002F React figures out HOW to transition the real DOM to match.\n\u002F\u002F You NEVER write: document.createElement, element.appendChild, etc.\n\n\u002F\u002F Components are plain functions. Props are arguments. JSX is syntax sugar.\n\u002F\u002F Logic reuse is JS composition (hooks, custom hooks), not template DSLs.\n\n\u002F\u002F DECLARATIVE vs IMPERATIVE:\n\u002F\u002F Imperative (jQuery): find element → update text → add class → attach listener\n\u002F\u002F Declarative (React): set state → React re-renders → DOM is updated automatically\n","",[30,31,32,41,47,53,60,66,72,78,84,90,96,101,107,113,118,124,130],"code",{"__ignoreMap":28},[33,34,37],"span",{"class":35,"line":36},"line",1,[33,38,40],{"class":39},"sdCPZ","\u002F\u002F React = a declarative, component-based UI library. Not a framework.\n",[33,42,44],{"class":35,"line":43},2,[33,45,46],{"class":39},"\u002F\u002F No router, no data layer, no state manager. ONE job: keep the UI in sync\n",[33,48,50],{"class":35,"line":49},3,[33,51,52],{"class":39},"\u002F\u002F with your data via virtual DOM diffing and unidirectional data flow.\n",[33,54,56],{"class":35,"line":55},4,[33,57,59],{"emptyLinePlaceholder":58},true,"\n",[33,61,63],{"class":35,"line":62},5,[33,64,65],{"class":39},"\u002F\u002F THE MENTAL MODEL:\n",[33,67,69],{"class":35,"line":68},6,[33,70,71],{"class":39},"\u002F\u002F   state → render → virtual DOM → diff → commit to real DOM\n",[33,73,75],{"class":35,"line":74},7,[33,76,77],{"class":39},"\u002F\u002F\n",[33,79,81],{"class":35,"line":80},8,[33,82,83],{"class":39},"\u002F\u002F You describe WHAT the UI should look like for a given state.\n",[33,85,87],{"class":35,"line":86},9,[33,88,89],{"class":39},"\u002F\u002F React figures out HOW to transition the real DOM to match.\n",[33,91,93],{"class":35,"line":92},10,[33,94,95],{"class":39},"\u002F\u002F You NEVER write: document.createElement, element.appendChild, etc.\n",[33,97,99],{"class":35,"line":98},11,[33,100,59],{"emptyLinePlaceholder":58},[33,102,104],{"class":35,"line":103},12,[33,105,106],{"class":39},"\u002F\u002F Components are plain functions. Props are arguments. JSX is syntax sugar.\n",[33,108,110],{"class":35,"line":109},13,[33,111,112],{"class":39},"\u002F\u002F Logic reuse is JS composition (hooks, custom hooks), not template DSLs.\n",[33,114,116],{"class":35,"line":115},14,[33,117,59],{"emptyLinePlaceholder":58},[33,119,121],{"class":35,"line":120},15,[33,122,123],{"class":39},"\u002F\u002F DECLARATIVE vs IMPERATIVE:\n",[33,125,127],{"class":35,"line":126},16,[33,128,129],{"class":39},"\u002F\u002F Imperative (jQuery): find element → update text → add class → attach listener\n",[33,131,133],{"class":35,"line":132},17,[33,134,135],{"class":39},"\u002F\u002F Declarative (React): set state → React re-renders → DOM is updated automatically\n",[14,137,139],{"id":138},"mounting-createroot-and-concurrent-rendering","Mounting: createRoot and Concurrent Rendering",[19,141,143],{"filename":142,"language":22},"mounting.js",[24,144,146],{"className":26,"code":145,"language":22,"meta":28,"style":28},"import { createRoot } from 'react-dom\u002Fclient'\nimport App from '.\u002FApp'\n\n\u002F\u002F React 18+: createRoot enables concurrent features (automatic batching,\n\u002F\u002F transitions, Suspense for data fetching). The legacy ReactDOM.render is deprecated.\nconst root = createRoot(document.getElementById('root'))\nroot.render(\u003CApp \u002F>)\n\n\u002F\u002F createRoot returns a root object with:\n\u002F\u002F   root.render(jsx)     — re-render (usually called once; React handles the rest)\n\u002F\u002F   root.unmount()       — tear down the entire tree, clean up all effects\n\n\u002F\u002F If you're hydrating SSR markup:\n\u002F\u002F import { hydrateRoot } from 'react-dom\u002Fclient'\n\u002F\u002F const root = hydrateRoot(document.getElementById('root'), \u003CApp \u002F>)\n\u002F\u002F — must match the server-rendered HTML exactly or React warns.\n",[30,147,148,165,177,181,186,191,222,239,243,248,253,258,262,267,272,277],{"__ignoreMap":28},[33,149,150,154,158,161],{"class":35,"line":36},[33,151,153],{"class":152},"svdQ7","import",[33,155,157],{"class":156},"ssxIu"," { createRoot } ",[33,159,160],{"class":152},"from",[33,162,164],{"class":163},"sJ6F3"," 'react-dom\u002Fclient'\n",[33,166,167,169,172,174],{"class":35,"line":43},[33,168,153],{"class":152},[33,170,171],{"class":156}," App ",[33,173,160],{"class":152},[33,175,176],{"class":163}," '.\u002FApp'\n",[33,178,179],{"class":35,"line":49},[33,180,59],{"emptyLinePlaceholder":58},[33,182,183],{"class":35,"line":55},[33,184,185],{"class":39},"\u002F\u002F React 18+: createRoot enables concurrent features (automatic batching,\n",[33,187,188],{"class":35,"line":62},[33,189,190],{"class":39},"\u002F\u002F transitions, Suspense for data fetching). The legacy ReactDOM.render is deprecated.\n",[33,192,193,196,200,203,207,210,213,216,219],{"class":35,"line":68},[33,194,195],{"class":152},"const",[33,197,199],{"class":198},"snvgF"," root",[33,201,202],{"class":152}," =",[33,204,206],{"class":205},"sIsaT"," createRoot",[33,208,209],{"class":156},"(document.",[33,211,212],{"class":205},"getElementById",[33,214,215],{"class":156},"(",[33,217,218],{"class":163},"'root'",[33,220,221],{"class":156},"))\n",[33,223,224,227,230,233,236],{"class":35,"line":74},[33,225,226],{"class":156},"root.",[33,228,229],{"class":205},"render",[33,231,232],{"class":156},"(\u003C",[33,234,235],{"class":198},"App",[33,237,238],{"class":156}," \u002F>)\n",[33,240,241],{"class":35,"line":80},[33,242,59],{"emptyLinePlaceholder":58},[33,244,245],{"class":35,"line":86},[33,246,247],{"class":39},"\u002F\u002F createRoot returns a root object with:\n",[33,249,250],{"class":35,"line":92},[33,251,252],{"class":39},"\u002F\u002F   root.render(jsx)     — re-render (usually called once; React handles the rest)\n",[33,254,255],{"class":35,"line":98},[33,256,257],{"class":39},"\u002F\u002F   root.unmount()       — tear down the entire tree, clean up all effects\n",[33,259,260],{"class":35,"line":103},[33,261,59],{"emptyLinePlaceholder":58},[33,263,264],{"class":35,"line":109},[33,265,266],{"class":39},"\u002F\u002F If you're hydrating SSR markup:\n",[33,268,269],{"class":35,"line":115},[33,270,271],{"class":39},"\u002F\u002F import { hydrateRoot } from 'react-dom\u002Fclient'\n",[33,273,274],{"class":35,"line":120},[33,275,276],{"class":39},"\u002F\u002F const root = hydrateRoot(document.getElementById('root'), \u003CApp \u002F>)\n",[33,278,279],{"class":35,"line":126},[33,280,281],{"class":39},"\u002F\u002F — must match the server-rendered HTML exactly or React warns.\n",[14,283,285],{"id":284},"project-scaffolding-vite","Project Scaffolding: Vite",[19,287,290],{"filename":288,"language":289},"scaffold.sh","bash",[24,291,294],{"className":292,"code":293,"language":289,"meta":28,"style":28},"language-bash shiki shiki-themes github-light github-dark","# Vite is the standard for new React projects (CRA is deprecated).\n# Fast dev server (esbuild), optimized build (Rollup), HMR out of the box.\n\nnpm create vite@latest my-app -- --template react\ncd my-app && npm install && npm run dev\n\n# For TypeScript:\nnpm create vite@latest my-app -- --template react-ts\n",[30,295,296,301,306,310,333,358,362,367],{"__ignoreMap":28},[33,297,298],{"class":35,"line":36},[33,299,300],{"class":39},"# Vite is the standard for new React projects (CRA is deprecated).\n",[33,302,303],{"class":35,"line":43},[33,304,305],{"class":39},"# Fast dev server (esbuild), optimized build (Rollup), HMR out of the box.\n",[33,307,308],{"class":35,"line":49},[33,309,59],{"emptyLinePlaceholder":58},[33,311,312,315,318,321,324,327,330],{"class":35,"line":55},[33,313,314],{"class":205},"npm",[33,316,317],{"class":163}," create",[33,319,320],{"class":163}," vite@latest",[33,322,323],{"class":163}," my-app",[33,325,326],{"class":198}," --",[33,328,329],{"class":198}," --template",[33,331,332],{"class":163}," react\n",[33,334,335,338,340,343,345,348,350,352,355],{"class":35,"line":62},[33,336,337],{"class":198},"cd",[33,339,323],{"class":163},[33,341,342],{"class":156}," && ",[33,344,314],{"class":205},[33,346,347],{"class":163}," install",[33,349,342],{"class":156},[33,351,314],{"class":205},[33,353,354],{"class":163}," run",[33,356,357],{"class":163}," dev\n",[33,359,360],{"class":35,"line":68},[33,361,59],{"emptyLinePlaceholder":58},[33,363,364],{"class":35,"line":74},[33,365,366],{"class":39},"# For TypeScript:\n",[33,368,369,371,373,375,377,379,381],{"class":35,"line":80},[33,370,314],{"class":205},[33,372,317],{"class":163},[33,374,320],{"class":163},[33,376,323],{"class":163},[33,378,326],{"class":198},[33,380,329],{"class":198},[33,382,383],{"class":163}," react-ts\n",[19,385,388],{"filename":386,"language":387},"package.json","json",[24,389,392],{"className":390,"code":391,"language":387,"meta":28,"style":28},"language-json shiki shiki-themes github-light github-dark","{\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"react\": \"^19.0.0\",\n    \"react-dom\": \"^19.0.0\"\n  },\n  \"devDependencies\": {\n    \"@vitejs\u002Fplugin-react\": \"^4.3.0\",\n    \"vite\": \"^6.0.0\"\n  }\n}\n",[30,393,394,399,407,421,433,443,448,455,467,477,481,488,500,510,515],{"__ignoreMap":28},[33,395,396],{"class":35,"line":36},[33,397,398],{"class":156},"{\n",[33,400,401,404],{"class":35,"line":43},[33,402,403],{"class":198},"  \"scripts\"",[33,405,406],{"class":156},": {\n",[33,408,409,412,415,418],{"class":35,"line":49},[33,410,411],{"class":198},"    \"dev\"",[33,413,414],{"class":156},": ",[33,416,417],{"class":163},"\"vite\"",[33,419,420],{"class":156},",\n",[33,422,423,426,428,431],{"class":35,"line":55},[33,424,425],{"class":198},"    \"build\"",[33,427,414],{"class":156},[33,429,430],{"class":163},"\"vite build\"",[33,432,420],{"class":156},[33,434,435,438,440],{"class":35,"line":62},[33,436,437],{"class":198},"    \"preview\"",[33,439,414],{"class":156},[33,441,442],{"class":163},"\"vite preview\"\n",[33,444,445],{"class":35,"line":68},[33,446,447],{"class":156},"  },\n",[33,449,450,453],{"class":35,"line":74},[33,451,452],{"class":198},"  \"dependencies\"",[33,454,406],{"class":156},[33,456,457,460,462,465],{"class":35,"line":80},[33,458,459],{"class":198},"    \"react\"",[33,461,414],{"class":156},[33,463,464],{"class":163},"\"^19.0.0\"",[33,466,420],{"class":156},[33,468,469,472,474],{"class":35,"line":86},[33,470,471],{"class":198},"    \"react-dom\"",[33,473,414],{"class":156},[33,475,476],{"class":163},"\"^19.0.0\"\n",[33,478,479],{"class":35,"line":92},[33,480,447],{"class":156},[33,482,483,486],{"class":35,"line":98},[33,484,485],{"class":198},"  \"devDependencies\"",[33,487,406],{"class":156},[33,489,490,493,495,498],{"class":35,"line":103},[33,491,492],{"class":198},"    \"@vitejs\u002Fplugin-react\"",[33,494,414],{"class":156},[33,496,497],{"class":163},"\"^4.3.0\"",[33,499,420],{"class":156},[33,501,502,505,507],{"class":35,"line":109},[33,503,504],{"class":198},"    \"vite\"",[33,506,414],{"class":156},[33,508,509],{"class":163},"\"^6.0.0\"\n",[33,511,512],{"class":35,"line":115},[33,513,514],{"class":156},"  }\n",[33,516,517],{"class":35,"line":120},[33,518,519],{"class":156},"}\n",[19,521,523],{"filename":522,"language":22},"vite.config.js",[24,524,526],{"className":26,"code":525,"language":22,"meta":28,"style":28},"import { defineConfig } from 'vite'\nimport react from '@vitejs\u002Fplugin-react'\n\nexport default defineConfig({\n  plugins: [react()],\n  server: {\n    port: 3000,\n    open: true,  \u002F\u002F auto-open browser on dev start\n  },\n  build: {\n    outDir: 'dist',\n    sourcemap: true,  \u002F\u002F production sourcemaps for debugging\n  },\n})\n",[30,527,528,540,552,556,570,581,586,596,610,614,619,629,641,645],{"__ignoreMap":28},[33,529,530,532,535,537],{"class":35,"line":36},[33,531,153],{"class":152},[33,533,534],{"class":156}," { defineConfig } ",[33,536,160],{"class":152},[33,538,539],{"class":163}," 'vite'\n",[33,541,542,544,547,549],{"class":35,"line":43},[33,543,153],{"class":152},[33,545,546],{"class":156}," react ",[33,548,160],{"class":152},[33,550,551],{"class":163}," '@vitejs\u002Fplugin-react'\n",[33,553,554],{"class":35,"line":49},[33,555,59],{"emptyLinePlaceholder":58},[33,557,558,561,564,567],{"class":35,"line":55},[33,559,560],{"class":152},"export",[33,562,563],{"class":152}," default",[33,565,566],{"class":205}," defineConfig",[33,568,569],{"class":156},"({\n",[33,571,572,575,578],{"class":35,"line":62},[33,573,574],{"class":156},"  plugins: [",[33,576,577],{"class":205},"react",[33,579,580],{"class":156},"()],\n",[33,582,583],{"class":35,"line":68},[33,584,585],{"class":156},"  server: {\n",[33,587,588,591,594],{"class":35,"line":74},[33,589,590],{"class":156},"    port: ",[33,592,593],{"class":198},"3000",[33,595,420],{"class":156},[33,597,598,601,604,607],{"class":35,"line":80},[33,599,600],{"class":156},"    open: ",[33,602,603],{"class":198},"true",[33,605,606],{"class":156},",  ",[33,608,609],{"class":39},"\u002F\u002F auto-open browser on dev start\n",[33,611,612],{"class":35,"line":86},[33,613,447],{"class":156},[33,615,616],{"class":35,"line":92},[33,617,618],{"class":156},"  build: {\n",[33,620,621,624,627],{"class":35,"line":98},[33,622,623],{"class":156},"    outDir: ",[33,625,626],{"class":163},"'dist'",[33,628,420],{"class":156},[33,630,631,634,636,638],{"class":35,"line":103},[33,632,633],{"class":156},"    sourcemap: ",[33,635,603],{"class":198},[33,637,606],{"class":156},[33,639,640],{"class":39},"\u002F\u002F production sourcemaps for debugging\n",[33,642,643],{"class":35,"line":109},[33,644,447],{"class":156},[33,646,647],{"class":35,"line":115},[33,648,649],{"class":156},"})\n",[14,651,653],{"id":652},"production-project-structure","Production Project Structure",[19,655,658],{"filename":656,"language":657},"project_structure.txt","text",[24,659,663],{"className":660,"code":662,"language":657},[661],"language-text","src\u002F\n├── main.jsx               # entry — createRoot().render(\u003CApp\u002F>)\n├── App.jsx                # root component, router setup\n├── components\u002F\n│   ├── ui\u002F                # generic reusable: Button, Input, Modal\n│   └── features\u002F          # domain-specific: ProductCard, UserMenu\n├── hooks\u002F                 # custom hooks: useDebounce, useFetch, useAuth\n├── context\u002F               # context providers: AuthContext, ThemeContext\n├── lib\u002F                   # third-party config: api client, analytics\n├── utils\u002F                 # pure helpers: formatDate, parseQuery\n├── assets\u002F                # images, fonts, icons (if not in public\u002F)\n└── styles\u002F                # global CSS, theme variables\n",[30,664,662],{"__ignoreMap":28},[14,666,668],{"id":667},"strict-mode-what-it-catches","Strict Mode: What It Catches",[19,670,672],{"filename":671,"language":22},"strict_mode.js",[24,673,675],{"className":26,"code":674,"language":22,"meta":28,"style":28},"import { StrictMode } from 'react'\n\n\u002F\u002F StrictMode renders components TWICE in development (not production).\n\u002F\u002F It also re-runs effects (mount → unmount → mount) to surface bugs.\n\u002F\u002F This is intentional — it catches:\n\u002F\u002F   1. Impure renders (side effects in render body)\n\u002F\u002F   2. Missing effect cleanups\n\u002F\u002F   3. Stale state from mutations\n\u002F\u002F The double-invoke is DEV ONLY — production renders once.\n\ncreateRoot(rootEl).render(\n  \u003CStrictMode>\n    \u003CApp \u002F>\n  \u003C\u002FStrictMode>\n)\n\n\u002F\u002F EXAMPLE of what StrictMode catches:\nfunction BuggyComponent() {\n  const [count, setCount] = useState(0)\n  \u002F\u002F ANTI-PATTERN: side effect in render body\n  console.log('rendering')  \u002F\u002F runs TWICE per state change in StrictMode\n  document.title = `Count: ${count}`  \u002F\u002F mutation during render — SHOULD be in useEffect\n  return \u003Cbutton onClick={() => setCount(c => c + 1)}>{count}\u003C\u002Fbutton>\n}\n\u002F\u002F StrictMode makes the double-render visible so you catch the impurity in dev,\n\u002F\u002F not in production where it causes subtle state desync.\n",[30,676,677,689,693,698,703,708,713,718,723,728,732,745,756,766,775,780,784,789,801,835,841,861,880,932,937,943],{"__ignoreMap":28},[33,678,679,681,684,686],{"class":35,"line":36},[33,680,153],{"class":152},[33,682,683],{"class":156}," { StrictMode } ",[33,685,160],{"class":152},[33,687,688],{"class":163}," 'react'\n",[33,690,691],{"class":35,"line":43},[33,692,59],{"emptyLinePlaceholder":58},[33,694,695],{"class":35,"line":49},[33,696,697],{"class":39},"\u002F\u002F StrictMode renders components TWICE in development (not production).\n",[33,699,700],{"class":35,"line":55},[33,701,702],{"class":39},"\u002F\u002F It also re-runs effects (mount → unmount → mount) to surface bugs.\n",[33,704,705],{"class":35,"line":62},[33,706,707],{"class":39},"\u002F\u002F This is intentional — it catches:\n",[33,709,710],{"class":35,"line":68},[33,711,712],{"class":39},"\u002F\u002F   1. Impure renders (side effects in render body)\n",[33,714,715],{"class":35,"line":74},[33,716,717],{"class":39},"\u002F\u002F   2. Missing effect cleanups\n",[33,719,720],{"class":35,"line":80},[33,721,722],{"class":39},"\u002F\u002F   3. Stale state from mutations\n",[33,724,725],{"class":35,"line":86},[33,726,727],{"class":39},"\u002F\u002F The double-invoke is DEV ONLY — production renders once.\n",[33,729,730],{"class":35,"line":92},[33,731,59],{"emptyLinePlaceholder":58},[33,733,734,737,740,742],{"class":35,"line":98},[33,735,736],{"class":205},"createRoot",[33,738,739],{"class":156},"(rootEl).",[33,741,229],{"class":205},[33,743,744],{"class":156},"(\n",[33,746,747,750,753],{"class":35,"line":103},[33,748,749],{"class":156},"  \u003C",[33,751,752],{"class":198},"StrictMode",[33,754,755],{"class":156},">\n",[33,757,758,761,763],{"class":35,"line":109},[33,759,760],{"class":156},"    \u003C",[33,762,235],{"class":198},[33,764,765],{"class":156}," \u002F>\n",[33,767,768,771,773],{"class":35,"line":115},[33,769,770],{"class":156},"  \u003C\u002F",[33,772,752],{"class":198},[33,774,755],{"class":156},[33,776,777],{"class":35,"line":120},[33,778,779],{"class":156},")\n",[33,781,782],{"class":35,"line":126},[33,783,59],{"emptyLinePlaceholder":58},[33,785,786],{"class":35,"line":132},[33,787,788],{"class":39},"\u002F\u002F EXAMPLE of what StrictMode catches:\n",[33,790,792,795,798],{"class":35,"line":791},18,[33,793,794],{"class":152},"function",[33,796,797],{"class":205}," BuggyComponent",[33,799,800],{"class":156},"() {\n",[33,802,804,807,810,813,816,819,822,825,828,830,833],{"class":35,"line":803},19,[33,805,806],{"class":152},"  const",[33,808,809],{"class":156}," [",[33,811,812],{"class":198},"count",[33,814,815],{"class":156},", ",[33,817,818],{"class":198},"setCount",[33,820,821],{"class":156},"] ",[33,823,824],{"class":152},"=",[33,826,827],{"class":205}," useState",[33,829,215],{"class":156},[33,831,832],{"class":198},"0",[33,834,779],{"class":156},[33,836,838],{"class":35,"line":837},20,[33,839,840],{"class":39},"  \u002F\u002F ANTI-PATTERN: side effect in render body\n",[33,842,844,847,850,852,855,858],{"class":35,"line":843},21,[33,845,846],{"class":156},"  console.",[33,848,849],{"class":205},"log",[33,851,215],{"class":156},[33,853,854],{"class":163},"'rendering'",[33,856,857],{"class":156},")  ",[33,859,860],{"class":39},"\u002F\u002F runs TWICE per state change in StrictMode\n",[33,862,864,867,869,872,874,877],{"class":35,"line":863},22,[33,865,866],{"class":156},"  document.title ",[33,868,824],{"class":152},[33,870,871],{"class":163}," `Count: ${",[33,873,812],{"class":156},[33,875,876],{"class":163},"}`",[33,878,879],{"class":39},"  \u002F\u002F mutation during render — SHOULD be in useEffect\n",[33,881,883,886,889,893,896,898,901,904,907,909,913,916,919,922,925,928,930],{"class":35,"line":882},23,[33,884,885],{"class":152},"  return",[33,887,888],{"class":156}," \u003C",[33,890,892],{"class":891},"sk71V","button",[33,894,895],{"class":205}," onClick",[33,897,824],{"class":152},[33,899,900],{"class":156},"{() ",[33,902,903],{"class":152},"=>",[33,905,906],{"class":205}," setCount",[33,908,215],{"class":156},[33,910,912],{"class":911},"sCrzJ","c",[33,914,915],{"class":152}," =>",[33,917,918],{"class":156}," c ",[33,920,921],{"class":152},"+",[33,923,924],{"class":198}," 1",[33,926,927],{"class":156},")}>{count}\u003C\u002F",[33,929,892],{"class":891},[33,931,755],{"class":156},[33,933,935],{"class":35,"line":934},24,[33,936,519],{"class":156},[33,938,940],{"class":35,"line":939},25,[33,941,942],{"class":39},"\u002F\u002F StrictMode makes the double-render visible so you catch the impurity in dev,\n",[33,944,946],{"class":35,"line":945},26,[33,947,948],{"class":39},"\u002F\u002F not in production where it causes subtle state desync.\n",[14,950,952],{"id":951},"jsx-javascript-compilation","JSX → JavaScript Compilation",[19,954,956],{"filename":955,"language":22},"jsx_compilation.js",[24,957,959],{"className":26,"code":958,"language":22,"meta":28,"style":28},"\u002F\u002F JSX is NOT HTML — it's syntax sugar for React.createElement calls.\n\u002F\u002F Babel\u002FSWC transforms it at build time.\n\n\u002F\u002F WHAT YOU WRITE:\nconst element = \u003Ch1 className=\"title\">Hello, {name}\u003C\u002Fh1>\n\n\u002F\u002F WHAT THE COMPILER PRODUCES:\nconst element = React.createElement('h1', { className: 'title' }, 'Hello, ', name)\n\n\u002F\u002F WHICH IS A PLAIN OBJECT:\n\u002F\u002F {\n\u002F\u002F   type: 'h1',\n\u002F\u002F   props: { className: 'title', children: ['Hello, ', name] },\n\u002F\u002F   key: null,\n\u002F\u002F   ref: null,\n\u002F\u002F   $$typeof: Symbol.for('react.element')  \u002F\u002F security: prevents XSS via injection\n\u002F\u002F }\n\n\u002F\u002F THE $$typeof SYMBOL is React's XSS defense — if a malicious script injects\n\u002F\u002F a JSON object that looks like a React element, it won't have the valid Symbol\n\u002F\u002F and React will refuse to render it. Symbols can't be serialized in JSON.\n",[30,960,961,966,971,975,980,1008,1012,1017,1051,1055,1060,1065,1070,1075,1080,1085,1093,1098,1102,1107,1112],{"__ignoreMap":28},[33,962,963],{"class":35,"line":36},[33,964,965],{"class":39},"\u002F\u002F JSX is NOT HTML — it's syntax sugar for React.createElement calls.\n",[33,967,968],{"class":35,"line":43},[33,969,970],{"class":39},"\u002F\u002F Babel\u002FSWC transforms it at build time.\n",[33,972,973],{"class":35,"line":49},[33,974,59],{"emptyLinePlaceholder":58},[33,976,977],{"class":35,"line":55},[33,978,979],{"class":39},"\u002F\u002F WHAT YOU WRITE:\n",[33,981,982,984,987,989,991,993,996,998,1001,1004,1006],{"class":35,"line":62},[33,983,195],{"class":152},[33,985,986],{"class":198}," element",[33,988,202],{"class":152},[33,990,888],{"class":156},[33,992,10],{"class":891},[33,994,995],{"class":205}," className",[33,997,824],{"class":152},[33,999,1000],{"class":163},"\"title\"",[33,1002,1003],{"class":156},">Hello, {name}\u003C\u002F",[33,1005,10],{"class":891},[33,1007,755],{"class":156},[33,1009,1010],{"class":35,"line":68},[33,1011,59],{"emptyLinePlaceholder":58},[33,1013,1014],{"class":35,"line":74},[33,1015,1016],{"class":39},"\u002F\u002F WHAT THE COMPILER PRODUCES:\n",[33,1018,1019,1021,1023,1025,1028,1031,1033,1036,1039,1042,1045,1048],{"class":35,"line":80},[33,1020,195],{"class":152},[33,1022,986],{"class":198},[33,1024,202],{"class":152},[33,1026,1027],{"class":156}," React.",[33,1029,1030],{"class":205},"createElement",[33,1032,215],{"class":156},[33,1034,1035],{"class":163},"'h1'",[33,1037,1038],{"class":156},", { className: ",[33,1040,1041],{"class":163},"'title'",[33,1043,1044],{"class":156}," }, ",[33,1046,1047],{"class":163},"'Hello, '",[33,1049,1050],{"class":156},", name)\n",[33,1052,1053],{"class":35,"line":86},[33,1054,59],{"emptyLinePlaceholder":58},[33,1056,1057],{"class":35,"line":92},[33,1058,1059],{"class":39},"\u002F\u002F WHICH IS A PLAIN OBJECT:\n",[33,1061,1062],{"class":35,"line":98},[33,1063,1064],{"class":39},"\u002F\u002F {\n",[33,1066,1067],{"class":35,"line":103},[33,1068,1069],{"class":39},"\u002F\u002F   type: 'h1',\n",[33,1071,1072],{"class":35,"line":109},[33,1073,1074],{"class":39},"\u002F\u002F   props: { className: 'title', children: ['Hello, ', name] },\n",[33,1076,1077],{"class":35,"line":115},[33,1078,1079],{"class":39},"\u002F\u002F   key: null,\n",[33,1081,1082],{"class":35,"line":120},[33,1083,1084],{"class":39},"\u002F\u002F   ref: null,\n",[33,1086,1087,1090],{"class":35,"line":126},[33,1088,1089],{"class":39},"\u002F\u002F   $$typeof: Symbol.for('react.element')",[33,1091,1092],{"class":39},"  \u002F\u002F security: prevents XSS via injection\n",[33,1094,1095],{"class":35,"line":132},[33,1096,1097],{"class":39},"\u002F\u002F }\n",[33,1099,1100],{"class":35,"line":791},[33,1101,59],{"emptyLinePlaceholder":58},[33,1103,1104],{"class":35,"line":803},[33,1105,1106],{"class":39},"\u002F\u002F THE $$typeof SYMBOL is React's XSS defense — if a malicious script injects\n",[33,1108,1109],{"class":35,"line":837},[33,1110,1111],{"class":39},"\u002F\u002F a JSON object that looks like a React element, it won't have the valid Symbol\n",[33,1113,1114],{"class":35,"line":843},[33,1115,1116],{"class":39},"\u002F\u002F and React will refuse to render it. Symbols can't be serialized in JSON.\n",[14,1118,1120],{"id":1119},"anti-pattern-direct-dom-manipulation","Anti-Pattern: Direct DOM Manipulation",[19,1122,1124],{"filename":1123,"language":22},"anti_pattern_dom.js",[24,1125,1127],{"className":26,"code":1126,"language":22,"meta":28,"style":28},"\u002F\u002F ANTI-PATTERN: mixing imperative DOM manipulation with React\nfunction BadInput() {\n  const ref = useRef()\n  useEffect(() => {\n    \u002F\u002F DON'T do this — React already manages this DOM node\n    ref.current.style.color = 'red'\n    ref.current.setAttribute('data-custom', 'true')\n  }, [])\n  return \u003Cinput ref={ref} \u002F>\n  \u002F\u002F If React re-renders and replaces this node, your manual attributes are lost.\n  \u002F\u002F The DOM is React's output — don't fight it from the outside.\n}\n\n\u002F\u002F PRODUCTION: let React manage the DOM, use state for dynamic values\nfunction GoodInput({ isValid }) {\n  return \u003Cinput style={{ color: isValid ? 'inherit' : 'red' }} data-custom={isValid} \u002F>\n}\n\u002F\u002F React reconciles style and attributes — no manual DOM touches needed.\n\u002F\u002F Use refs ONLY for: focus management, scroll position, measuring layout,\n\u002F\u002F integrating with non-React libraries (Chapter 8).\n",[30,1128,1129,1134,1143,1158,1171,1176,1186,1206,1211,1227,1232,1237,1241,1245,1250,1266,1305,1309,1314,1319],{"__ignoreMap":28},[33,1130,1131],{"class":35,"line":36},[33,1132,1133],{"class":39},"\u002F\u002F ANTI-PATTERN: mixing imperative DOM manipulation with React\n",[33,1135,1136,1138,1141],{"class":35,"line":43},[33,1137,794],{"class":152},[33,1139,1140],{"class":205}," BadInput",[33,1142,800],{"class":156},[33,1144,1145,1147,1150,1152,1155],{"class":35,"line":49},[33,1146,806],{"class":152},[33,1148,1149],{"class":198}," ref",[33,1151,202],{"class":152},[33,1153,1154],{"class":205}," useRef",[33,1156,1157],{"class":156},"()\n",[33,1159,1160,1163,1166,1168],{"class":35,"line":55},[33,1161,1162],{"class":205},"  useEffect",[33,1164,1165],{"class":156},"(() ",[33,1167,903],{"class":152},[33,1169,1170],{"class":156}," {\n",[33,1172,1173],{"class":35,"line":62},[33,1174,1175],{"class":39},"    \u002F\u002F DON'T do this — React already manages this DOM node\n",[33,1177,1178,1181,1183],{"class":35,"line":68},[33,1179,1180],{"class":156},"    ref.current.style.color ",[33,1182,824],{"class":152},[33,1184,1185],{"class":163}," 'red'\n",[33,1187,1188,1191,1194,1196,1199,1201,1204],{"class":35,"line":74},[33,1189,1190],{"class":156},"    ref.current.",[33,1192,1193],{"class":205},"setAttribute",[33,1195,215],{"class":156},[33,1197,1198],{"class":163},"'data-custom'",[33,1200,815],{"class":156},[33,1202,1203],{"class":163},"'true'",[33,1205,779],{"class":156},[33,1207,1208],{"class":35,"line":80},[33,1209,1210],{"class":156},"  }, [])\n",[33,1212,1213,1215,1217,1220,1222,1224],{"class":35,"line":86},[33,1214,885],{"class":152},[33,1216,888],{"class":156},[33,1218,1219],{"class":891},"input",[33,1221,1149],{"class":205},[33,1223,824],{"class":152},[33,1225,1226],{"class":156},"{ref} \u002F>\n",[33,1228,1229],{"class":35,"line":92},[33,1230,1231],{"class":39},"  \u002F\u002F If React re-renders and replaces this node, your manual attributes are lost.\n",[33,1233,1234],{"class":35,"line":98},[33,1235,1236],{"class":39},"  \u002F\u002F The DOM is React's output — don't fight it from the outside.\n",[33,1238,1239],{"class":35,"line":103},[33,1240,519],{"class":156},[33,1242,1243],{"class":35,"line":109},[33,1244,59],{"emptyLinePlaceholder":58},[33,1246,1247],{"class":35,"line":115},[33,1248,1249],{"class":39},"\u002F\u002F PRODUCTION: let React manage the DOM, use state for dynamic values\n",[33,1251,1252,1254,1257,1260,1263],{"class":35,"line":120},[33,1253,794],{"class":152},[33,1255,1256],{"class":205}," GoodInput",[33,1258,1259],{"class":156},"({ ",[33,1261,1262],{"class":911},"isValid",[33,1264,1265],{"class":156}," }) {\n",[33,1267,1268,1270,1272,1274,1277,1279,1282,1285,1288,1291,1294,1297,1300,1302],{"class":35,"line":126},[33,1269,885],{"class":152},[33,1271,888],{"class":156},[33,1273,1219],{"class":891},[33,1275,1276],{"class":205}," style",[33,1278,824],{"class":152},[33,1280,1281],{"class":156},"{{ color: isValid ",[33,1283,1284],{"class":152},"?",[33,1286,1287],{"class":163}," 'inherit'",[33,1289,1290],{"class":152}," :",[33,1292,1293],{"class":163}," 'red'",[33,1295,1296],{"class":156}," }} ",[33,1298,1299],{"class":205},"data-custom",[33,1301,824],{"class":152},[33,1303,1304],{"class":156},"{isValid} \u002F>\n",[33,1306,1307],{"class":35,"line":132},[33,1308,519],{"class":156},[33,1310,1311],{"class":35,"line":791},[33,1312,1313],{"class":39},"\u002F\u002F React reconciles style and attributes — no manual DOM touches needed.\n",[33,1315,1316],{"class":35,"line":803},[33,1317,1318],{"class":39},"\u002F\u002F Use refs ONLY for: focus management, scroll position, measuring layout,\n",[33,1320,1321],{"class":35,"line":837},[33,1322,1323],{"class":39},"\u002F\u002F integrating with non-React libraries (Chapter 8).\n",[14,1325,1327],{"id":1326},"tips-tricks","💡 Tips & Tricks",[19,1329,1331],{"filename":1330,"language":22},"tips.js",[24,1332,1334],{"className":26,"code":1333,"language":22,"meta":28,"style":28},"\u002F\u002F [Idiom] Always use createRoot (React 18+), never ReactDOM.render — it's\n\u002F\u002F deprecated and doesn't support concurrent features, automatic batching,\n\u002F\u002F or transitions.\n\n\u002F\u002F [Debug] If your app renders twice on every state update in dev, check\n\u002F\u002F StrictMode first — it's intentional, not a bug. It disappears in production.\n\n\u002F\u002F [Performance] Vite's dev server uses esbuild (Go-based) — orders of magnitude\n\u002F\u002F faster than Babel for JSX transformation. Only the production build uses\n\u002F\u002F Rollup for tree-shaking and code-splitting.\n\n\u002F\u002F [Idiom] Keep main.jsx minimal — just createRoot + render + global providers.\n\u002F\u002F All routing, layout, and logic belongs in App.jsx or child components.\n\n\u002F\u002F [Safety] The $$typeof Symbol.for('react.element') check is React's built-in\n\u002F\u002F XSS defense. Never bypass it by manually constructing element objects —\n\u002F\u002F always use JSX or React.createElement.\n",[30,1335,1336,1341,1346,1351,1355,1360,1365,1369,1374,1379,1384,1388,1393,1398,1402,1407,1412],{"__ignoreMap":28},[33,1337,1338],{"class":35,"line":36},[33,1339,1340],{"class":39},"\u002F\u002F [Idiom] Always use createRoot (React 18+), never ReactDOM.render — it's\n",[33,1342,1343],{"class":35,"line":43},[33,1344,1345],{"class":39},"\u002F\u002F deprecated and doesn't support concurrent features, automatic batching,\n",[33,1347,1348],{"class":35,"line":49},[33,1349,1350],{"class":39},"\u002F\u002F or transitions.\n",[33,1352,1353],{"class":35,"line":55},[33,1354,59],{"emptyLinePlaceholder":58},[33,1356,1357],{"class":35,"line":62},[33,1358,1359],{"class":39},"\u002F\u002F [Debug] If your app renders twice on every state update in dev, check\n",[33,1361,1362],{"class":35,"line":68},[33,1363,1364],{"class":39},"\u002F\u002F StrictMode first — it's intentional, not a bug. It disappears in production.\n",[33,1366,1367],{"class":35,"line":74},[33,1368,59],{"emptyLinePlaceholder":58},[33,1370,1371],{"class":35,"line":80},[33,1372,1373],{"class":39},"\u002F\u002F [Performance] Vite's dev server uses esbuild (Go-based) — orders of magnitude\n",[33,1375,1376],{"class":35,"line":86},[33,1377,1378],{"class":39},"\u002F\u002F faster than Babel for JSX transformation. Only the production build uses\n",[33,1380,1381],{"class":35,"line":92},[33,1382,1383],{"class":39},"\u002F\u002F Rollup for tree-shaking and code-splitting.\n",[33,1385,1386],{"class":35,"line":98},[33,1387,59],{"emptyLinePlaceholder":58},[33,1389,1390],{"class":35,"line":103},[33,1391,1392],{"class":39},"\u002F\u002F [Idiom] Keep main.jsx minimal — just createRoot + render + global providers.\n",[33,1394,1395],{"class":35,"line":109},[33,1396,1397],{"class":39},"\u002F\u002F All routing, layout, and logic belongs in App.jsx or child components.\n",[33,1399,1400],{"class":35,"line":115},[33,1401,59],{"emptyLinePlaceholder":58},[33,1403,1404],{"class":35,"line":120},[33,1405,1406],{"class":39},"\u002F\u002F [Safety] The $$typeof Symbol.for('react.element') check is React's built-in\n",[33,1408,1409],{"class":35,"line":126},[33,1410,1411],{"class":39},"\u002F\u002F XSS defense. Never bypass it by manually constructing element objects —\n",[33,1413,1414],{"class":35,"line":132},[33,1415,1416],{"class":39},"\u002F\u002F always use JSX or React.createElement.\n",[14,1418,1420],{"id":1419},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[19,1422,1424],{"filename":1423,"language":22},"edge_cases.js",[24,1425,1427],{"className":26,"code":1426,"language":22,"meta":28,"style":28},"\u002F\u002F [Gotcha] StrictMode double-invokes effects (mount → unmount → mount) in dev.\n\u002F\u002F If your effect creates a WebSocket connection without cleanup, you'll get\n\u002F\u002F TWO connections in dev. Always implement cleanup in useEffect.\n\n\u002F\u002F [Gotcha] createRoot can only be called ONCE per DOM element. Calling\n\u002F\u002F root.render() multiple times is fine (it updates), but creating two roots\n\u002F\u002F on the same element throws. To update, reuse the root object.\n\n\u002F\u002F [Gotcha] ReactDOM.render (legacy) and createRoot have different batching\n\u002F\u002F behavior — legacy doesn't batch outside React event handlers; createRoot\n\u002F\u002F (React 18+) batches EVERYTHING (timeouts, promises, native events).\n\n\u002F\u002F [Gotcha] If you see \"Target container is not a DOM element\" — your script\n\u002F\u002F is running before the DOM is ready. Ensure the script tag has defer, or\n\u002F\u002F your entry point runs after the #root element exists in the document.\n\n\u002F\u002F [Gotcha] Hydration mismatch warnings occur when server-rendered HTML differs\n\u002F\u002F from what React expects on the client. Common causes: timestamps, Math.random(),\n\u002F\u002F browser-only APIs in the initial render, or different data between server and client.\n",[30,1428,1429,1434,1439,1444,1448,1453,1458,1463,1467,1472,1477,1482,1486,1491,1496,1501,1505,1510,1515],{"__ignoreMap":28},[33,1430,1431],{"class":35,"line":36},[33,1432,1433],{"class":39},"\u002F\u002F [Gotcha] StrictMode double-invokes effects (mount → unmount → mount) in dev.\n",[33,1435,1436],{"class":35,"line":43},[33,1437,1438],{"class":39},"\u002F\u002F If your effect creates a WebSocket connection without cleanup, you'll get\n",[33,1440,1441],{"class":35,"line":49},[33,1442,1443],{"class":39},"\u002F\u002F TWO connections in dev. Always implement cleanup in useEffect.\n",[33,1445,1446],{"class":35,"line":55},[33,1447,59],{"emptyLinePlaceholder":58},[33,1449,1450],{"class":35,"line":62},[33,1451,1452],{"class":39},"\u002F\u002F [Gotcha] createRoot can only be called ONCE per DOM element. Calling\n",[33,1454,1455],{"class":35,"line":68},[33,1456,1457],{"class":39},"\u002F\u002F root.render() multiple times is fine (it updates), but creating two roots\n",[33,1459,1460],{"class":35,"line":74},[33,1461,1462],{"class":39},"\u002F\u002F on the same element throws. To update, reuse the root object.\n",[33,1464,1465],{"class":35,"line":80},[33,1466,59],{"emptyLinePlaceholder":58},[33,1468,1469],{"class":35,"line":86},[33,1470,1471],{"class":39},"\u002F\u002F [Gotcha] ReactDOM.render (legacy) and createRoot have different batching\n",[33,1473,1474],{"class":35,"line":92},[33,1475,1476],{"class":39},"\u002F\u002F behavior — legacy doesn't batch outside React event handlers; createRoot\n",[33,1478,1479],{"class":35,"line":98},[33,1480,1481],{"class":39},"\u002F\u002F (React 18+) batches EVERYTHING (timeouts, promises, native events).\n",[33,1483,1484],{"class":35,"line":103},[33,1485,59],{"emptyLinePlaceholder":58},[33,1487,1488],{"class":35,"line":109},[33,1489,1490],{"class":39},"\u002F\u002F [Gotcha] If you see \"Target container is not a DOM element\" — your script\n",[33,1492,1493],{"class":35,"line":115},[33,1494,1495],{"class":39},"\u002F\u002F is running before the DOM is ready. Ensure the script tag has defer, or\n",[33,1497,1498],{"class":35,"line":120},[33,1499,1500],{"class":39},"\u002F\u002F your entry point runs after the #root element exists in the document.\n",[33,1502,1503],{"class":35,"line":126},[33,1504,59],{"emptyLinePlaceholder":58},[33,1506,1507],{"class":35,"line":132},[33,1508,1509],{"class":39},"\u002F\u002F [Gotcha] Hydration mismatch warnings occur when server-rendered HTML differs\n",[33,1511,1512],{"class":35,"line":791},[33,1513,1514],{"class":39},"\u002F\u002F from what React expects on the client. Common causes: timestamps, Math.random(),\n",[33,1516,1517],{"class":35,"line":803},[33,1518,1519],{"class":39},"\u002F\u002F browser-only APIs in the initial render, or different data between server and client.\n",[14,1521,1523],{"id":1522},"spot-the-bug","🧠 Spot the Bug",[1525,1526,1527],"p",{},"A developer's component shows a value in the DOM that doesn't update when state changes:",[19,1529,1531],{"filename":1530,"language":22},"spot_the_bug.js",[24,1532,1534],{"className":26,"code":1533,"language":22,"meta":28,"style":28},"function Counter() {\n  const [count, setCount] = useState(0)\n  document.title = `Count: ${count}`  \u002F\u002F ← side effect in render body\n  return \u003Cbutton onClick={() => setCount(c => c + 1)}>Count: {count}\u003C\u002Fbutton>\n}\n",[30,1535,1536,1545,1569,1584,1621],{"__ignoreMap":28},[33,1537,1538,1540,1543],{"class":35,"line":36},[33,1539,794],{"class":152},[33,1541,1542],{"class":205}," Counter",[33,1544,800],{"class":156},[33,1546,1547,1549,1551,1553,1555,1557,1559,1561,1563,1565,1567],{"class":35,"line":43},[33,1548,806],{"class":152},[33,1550,809],{"class":156},[33,1552,812],{"class":198},[33,1554,815],{"class":156},[33,1556,818],{"class":198},[33,1558,821],{"class":156},[33,1560,824],{"class":152},[33,1562,827],{"class":205},[33,1564,215],{"class":156},[33,1566,832],{"class":198},[33,1568,779],{"class":156},[33,1570,1571,1573,1575,1577,1579,1581],{"class":35,"line":49},[33,1572,866],{"class":156},[33,1574,824],{"class":152},[33,1576,871],{"class":163},[33,1578,812],{"class":156},[33,1580,876],{"class":163},[33,1582,1583],{"class":39},"  \u002F\u002F ← side effect in render body\n",[33,1585,1586,1588,1590,1592,1594,1596,1598,1600,1602,1604,1606,1608,1610,1612,1614,1617,1619],{"class":35,"line":55},[33,1587,885],{"class":152},[33,1589,888],{"class":156},[33,1591,892],{"class":891},[33,1593,895],{"class":205},[33,1595,824],{"class":152},[33,1597,900],{"class":156},[33,1599,903],{"class":152},[33,1601,906],{"class":205},[33,1603,215],{"class":156},[33,1605,912],{"class":911},[33,1607,915],{"class":152},[33,1609,918],{"class":156},[33,1611,921],{"class":152},[33,1613,924],{"class":198},[33,1615,1616],{"class":156},")}>Count: {count}\u003C\u002F",[33,1618,892],{"class":891},[33,1620,755],{"class":156},[33,1622,1623],{"class":35,"line":62},[33,1624,519],{"class":156},[1525,1626,1627,1628,1631],{},"The button text updates, but ",[30,1629,1630],{},"document.title"," sometimes lags or shows the wrong value. Why?",[1633,1634,1635,1639,1662,1771],"details",{},[1636,1637,1638],"summary",{},"Answer",[1525,1640,1641,1644,1645,1648,1649,1653,1654,1656,1657,1661],{},[30,1642,1643],{},"document.title = ..."," runs in the render body, not in a ",[30,1646,1647],{},"useEffect",". React may render a component multiple times before committing to the DOM (especially in StrictMode, which double-invokes render). The render phase must be ",[1650,1651,1652],"strong",{},"pure"," — no side effects, no mutations. Side effects belong in ",[30,1655,1647],{},", which runs ",[1658,1659,1660],"em",{},"after"," the DOM commit:",[24,1663,1665],{"className":26,"code":1664,"language":22,"meta":28,"style":28},"function Counter() {\n  const [count, setCount] = useState(0)\n  useEffect(() => {\n    document.title = `Count: ${count}`\n  }, [count])  \u002F\u002F runs after commit, only when count changes\n  return \u003Cbutton onClick={() => setCount(c => c + 1)}>Count: {count}\u003C\u002Fbutton>\n}\n",[30,1666,1667,1675,1699,1709,1723,1731,1767],{"__ignoreMap":28},[33,1668,1669,1671,1673],{"class":35,"line":36},[33,1670,794],{"class":152},[33,1672,1542],{"class":205},[33,1674,800],{"class":156},[33,1676,1677,1679,1681,1683,1685,1687,1689,1691,1693,1695,1697],{"class":35,"line":43},[33,1678,806],{"class":152},[33,1680,809],{"class":156},[33,1682,812],{"class":198},[33,1684,815],{"class":156},[33,1686,818],{"class":198},[33,1688,821],{"class":156},[33,1690,824],{"class":152},[33,1692,827],{"class":205},[33,1694,215],{"class":156},[33,1696,832],{"class":198},[33,1698,779],{"class":156},[33,1700,1701,1703,1705,1707],{"class":35,"line":49},[33,1702,1162],{"class":205},[33,1704,1165],{"class":156},[33,1706,903],{"class":152},[33,1708,1170],{"class":156},[33,1710,1711,1714,1716,1718,1720],{"class":35,"line":55},[33,1712,1713],{"class":156},"    document.title ",[33,1715,824],{"class":152},[33,1717,871],{"class":163},[33,1719,812],{"class":156},[33,1721,1722],{"class":163},"}`\n",[33,1724,1725,1728],{"class":35,"line":62},[33,1726,1727],{"class":156},"  }, [count])  ",[33,1729,1730],{"class":39},"\u002F\u002F runs after commit, only when count changes\n",[33,1732,1733,1735,1737,1739,1741,1743,1745,1747,1749,1751,1753,1755,1757,1759,1761,1763,1765],{"class":35,"line":68},[33,1734,885],{"class":152},[33,1736,888],{"class":156},[33,1738,892],{"class":891},[33,1740,895],{"class":205},[33,1742,824],{"class":152},[33,1744,900],{"class":156},[33,1746,903],{"class":152},[33,1748,906],{"class":205},[33,1750,215],{"class":156},[33,1752,912],{"class":911},[33,1754,915],{"class":152},[33,1756,918],{"class":156},[33,1758,921],{"class":152},[33,1760,924],{"class":198},[33,1762,1616],{"class":156},[33,1764,892],{"class":891},[33,1766,755],{"class":156},[33,1768,1769],{"class":35,"line":74},[33,1770,519],{"class":156},[1525,1772,1773,1774,1776,1777,1779],{},"In StrictMode (dev), the render body runs twice per update — the ",[30,1775,1630],{}," gets set twice with potentially stale values from an abandoned render. In production it usually works by accident, but the render phase is not guaranteed to be a 1:1 mapping to commits. Move side effects to ",[30,1778,1647],{},".",[14,1781,1783],{"id":1782},"key-takeaways","Key Takeaways",[19,1785,1787],{"filename":1786,"language":22},"key_takeaways.js",[24,1788,1790],{"className":26,"code":1789,"language":22,"meta":28,"style":28},"\u002F\u002F 1. React = declarative UI library. You describe WHAT the UI looks like for\n\u002F\u002F    a given state; React diffs the virtual DOM and commits minimal real-DOM changes.\n\u002F\u002F    Never imperatively manipulate DOM that React manages.\n\n\u002F\u002F 2. createRoot (React 18+) enables concurrent features, automatic batching,\n\u002F\u002F    and transitions. Legacy ReactDOM.render is deprecated — don't use it.\n\n\u002F\u002F 3. Vite is the standard scaffold (CRA is deprecated). esbuild for dev speed,\n\u002F\u002F    Rollup for production builds. npm create vite@latest my-app -- --template react\n\n\u002F\u002F 4. StrictMode renders twice and re-runs effects in DEV to catch impure renders\n\u002F\u002F    and missing cleanups. This is intentional — it vanishes in production.\n\n\u002F\u002F 5. JSX compiles to React.createElement() calls → plain objects with\n\u002F\u002F    $$typeof: Symbol.for('react.element') as XSS defense. Never construct\n\u002F\u002F    element objects manually — always use JSX or createElement.\n",[30,1791,1792,1797,1802,1807,1811,1816,1821,1825,1830,1835,1839,1844,1849,1853,1858,1863],{"__ignoreMap":28},[33,1793,1794],{"class":35,"line":36},[33,1795,1796],{"class":39},"\u002F\u002F 1. React = declarative UI library. You describe WHAT the UI looks like for\n",[33,1798,1799],{"class":35,"line":43},[33,1800,1801],{"class":39},"\u002F\u002F    a given state; React diffs the virtual DOM and commits minimal real-DOM changes.\n",[33,1803,1804],{"class":35,"line":49},[33,1805,1806],{"class":39},"\u002F\u002F    Never imperatively manipulate DOM that React manages.\n",[33,1808,1809],{"class":35,"line":55},[33,1810,59],{"emptyLinePlaceholder":58},[33,1812,1813],{"class":35,"line":62},[33,1814,1815],{"class":39},"\u002F\u002F 2. createRoot (React 18+) enables concurrent features, automatic batching,\n",[33,1817,1818],{"class":35,"line":68},[33,1819,1820],{"class":39},"\u002F\u002F    and transitions. Legacy ReactDOM.render is deprecated — don't use it.\n",[33,1822,1823],{"class":35,"line":74},[33,1824,59],{"emptyLinePlaceholder":58},[33,1826,1827],{"class":35,"line":80},[33,1828,1829],{"class":39},"\u002F\u002F 3. Vite is the standard scaffold (CRA is deprecated). esbuild for dev speed,\n",[33,1831,1832],{"class":35,"line":86},[33,1833,1834],{"class":39},"\u002F\u002F    Rollup for production builds. npm create vite@latest my-app -- --template react\n",[33,1836,1837],{"class":35,"line":92},[33,1838,59],{"emptyLinePlaceholder":58},[33,1840,1841],{"class":35,"line":98},[33,1842,1843],{"class":39},"\u002F\u002F 4. StrictMode renders twice and re-runs effects in DEV to catch impure renders\n",[33,1845,1846],{"class":35,"line":103},[33,1847,1848],{"class":39},"\u002F\u002F    and missing cleanups. This is intentional — it vanishes in production.\n",[33,1850,1851],{"class":35,"line":109},[33,1852,59],{"emptyLinePlaceholder":58},[33,1854,1855],{"class":35,"line":115},[33,1856,1857],{"class":39},"\u002F\u002F 5. JSX compiles to React.createElement() calls → plain objects with\n",[33,1859,1860],{"class":35,"line":120},[33,1861,1862],{"class":39},"\u002F\u002F    $$typeof: Symbol.for('react.element') as XSS defense. Never construct\n",[33,1864,1865],{"class":35,"line":126},[33,1866,1867],{"class":39},"\u002F\u002F    element objects manually — always use JSX or createElement.\n",[1869,1870,1871],"style",{},"html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .sk71V, html code.shiki .sk71V{--shiki-default:#22863A;--shiki-github-dark:#85E89D}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}",{"title":28,"searchDepth":43,"depth":43,"links":1873},[1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884],{"id":16,"depth":43,"text":17},{"id":138,"depth":43,"text":139},{"id":284,"depth":43,"text":285},{"id":652,"depth":43,"text":653},{"id":667,"depth":43,"text":668},{"id":951,"depth":43,"text":952},{"id":1119,"depth":43,"text":1120},{"id":1326,"depth":43,"text":1327},{"id":1419,"depth":43,"text":1420},{"id":1522,"depth":43,"text":1523},{"id":1782,"depth":43,"text":1783},"React's declarative rendering model, virtual DOM diffing, project scaffolding with Vite, Strict Mode behavior, and the JSX-to-JS compilation pipeline. Code-first reference for mid-to-senior React engineers.","md",{},"\u002Freact\u002F01-introduction-and-setup",{"title":5,"description":1885},"react\u002F01-introduction-and-setup","ghaGi_X-OpdDFLJGeuMdh9T3awc8hI8Ypmb3Mpadydk",1789924651947]