[{"data":1,"prerenderedAt":2350},["ShallowReactive",2],{"page-\u002Freact\u002F02-jsx-deep-dive":3},{"id":4,"title":5,"body":6,"description":2343,"extension":2344,"meta":2345,"navigation":52,"path":2346,"seo":2347,"stem":2348,"__hash__":2349},"content\u002Freact\u002F02-jsx-deep-dive.md","02 — JSX Deep Dive",{"type":7,"value":8,"toc":2331},"minimark",[9,13,18,288,292,688,692,862,1006,1010,1250,1254,1544,1548,1796,1800,1879,1883,1967,1971,1974,2084,2244,2248,2327],[10,11,5],"h1",{"id":12},"_02-jsx-deep-dive",[14,15,17],"h2",{"id":16},"jsx-reactcreateelement","JSX → React.createElement",[19,20,23],"code-wrapper",{"filename":21,"language":22},"jsx_to_createelement.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 JSX is syntactic sugar for React.createElement. The compiler (Babel\u002FSWC)\n\u002F\u002F transforms it at build time — JSX never reaches the browser.\n\n\u002F\u002F WHAT YOU WRITE:\nconst greeting = \u003Ch1 className=\"title\" id=\"main\">Hello, {name}!\u003C\u002Fh1>\n\n\u002F\u002F WHAT THE COMPILER PRODUCES:\nconst greeting = React.createElement(\n  'h1',                          \u002F\u002F type: string (DOM) | function (component) | symbol (fragment)\n  { className: 'title', id: 'main' },  \u002F\u002F props object\n  'Hello, ',                     \u002F\u002F children...\n  name,\n  '!'\n)\n\n\u002F\u002F WHICH BECOMES THIS OBJECT:\n\u002F\u002F {\n\u002F\u002F   type: 'h1',\n\u002F\u002F   props: { className: 'title', id: 'main', children: ['Hello, ', name, '!'] },\n\u002F\u002F   key: null,\n\u002F\u002F   ref: null,\n\u002F\u002F   $$typeof: Symbol.for('react.element')\n\u002F\u002F }\n\n\u002F\u002F Knowing this explains WHY:\n\u002F\u002F - You can store JSX in variables: const el = \u003Cdiv\u002F>  (it's just an object)\n\u002F\u002F - You can pass JSX as props: \u003CCard header={\u003Ch1>Title\u003C\u002Fh1>} \u002F>\n\u002F\u002F - You can return JSX from functions: getIcon(name) → \u003Csvg\u002F>\n\u002F\u002F - You can't use if\u002Ffor\u002Fswitch INSIDE JSX — they're statements, not expressions\n","",[30,31,32,41,47,54,60,108,113,119,137,149,170,182,188,194,200,205,211,217,223,229,235,241,247,253,258,264,270,276,282],"code",{"__ignoreMap":28},[33,34,37],"span",{"class":35,"line":36},"line",1,[33,38,40],{"class":39},"sdCPZ","\u002F\u002F JSX is syntactic sugar for React.createElement. The compiler (Babel\u002FSWC)\n",[33,42,44],{"class":35,"line":43},2,[33,45,46],{"class":39},"\u002F\u002F transforms it at build time — JSX never reaches the browser.\n",[33,48,50],{"class":35,"line":49},3,[33,51,53],{"emptyLinePlaceholder":52},true,"\n",[33,55,57],{"class":35,"line":56},4,[33,58,59],{"class":39},"\u002F\u002F WHAT YOU WRITE:\n",[33,61,63,67,71,74,78,81,85,88,92,95,97,100,103,105],{"class":35,"line":62},5,[33,64,66],{"class":65},"svdQ7","const",[33,68,70],{"class":69},"snvgF"," greeting",[33,72,73],{"class":65}," =",[33,75,77],{"class":76},"ssxIu"," \u003C",[33,79,10],{"class":80},"sk71V",[33,82,84],{"class":83},"sIsaT"," className",[33,86,87],{"class":65},"=",[33,89,91],{"class":90},"sJ6F3","\"title\"",[33,93,94],{"class":83}," id",[33,96,87],{"class":65},[33,98,99],{"class":90},"\"main\"",[33,101,102],{"class":76},">Hello, {name}!\u003C\u002F",[33,104,10],{"class":80},[33,106,107],{"class":76},">\n",[33,109,111],{"class":35,"line":110},6,[33,112,53],{"emptyLinePlaceholder":52},[33,114,116],{"class":35,"line":115},7,[33,117,118],{"class":39},"\u002F\u002F WHAT THE COMPILER PRODUCES:\n",[33,120,122,124,126,128,131,134],{"class":35,"line":121},8,[33,123,66],{"class":65},[33,125,70],{"class":69},[33,127,73],{"class":65},[33,129,130],{"class":76}," React.",[33,132,133],{"class":83},"createElement",[33,135,136],{"class":76},"(\n",[33,138,140,143,146],{"class":35,"line":139},9,[33,141,142],{"class":90},"  'h1'",[33,144,145],{"class":76},",                          ",[33,147,148],{"class":39},"\u002F\u002F type: string (DOM) | function (component) | symbol (fragment)\n",[33,150,152,155,158,161,164,167],{"class":35,"line":151},10,[33,153,154],{"class":76},"  { className: ",[33,156,157],{"class":90},"'title'",[33,159,160],{"class":76},", id: ",[33,162,163],{"class":90},"'main'",[33,165,166],{"class":76}," },  ",[33,168,169],{"class":39},"\u002F\u002F props object\n",[33,171,173,176,179],{"class":35,"line":172},11,[33,174,175],{"class":90},"  'Hello, '",[33,177,178],{"class":76},",                     ",[33,180,181],{"class":39},"\u002F\u002F children...\n",[33,183,185],{"class":35,"line":184},12,[33,186,187],{"class":76},"  name,\n",[33,189,191],{"class":35,"line":190},13,[33,192,193],{"class":90},"  '!'\n",[33,195,197],{"class":35,"line":196},14,[33,198,199],{"class":76},")\n",[33,201,203],{"class":35,"line":202},15,[33,204,53],{"emptyLinePlaceholder":52},[33,206,208],{"class":35,"line":207},16,[33,209,210],{"class":39},"\u002F\u002F WHICH BECOMES THIS OBJECT:\n",[33,212,214],{"class":35,"line":213},17,[33,215,216],{"class":39},"\u002F\u002F {\n",[33,218,220],{"class":35,"line":219},18,[33,221,222],{"class":39},"\u002F\u002F   type: 'h1',\n",[33,224,226],{"class":35,"line":225},19,[33,227,228],{"class":39},"\u002F\u002F   props: { className: 'title', id: 'main', children: ['Hello, ', name, '!'] },\n",[33,230,232],{"class":35,"line":231},20,[33,233,234],{"class":39},"\u002F\u002F   key: null,\n",[33,236,238],{"class":35,"line":237},21,[33,239,240],{"class":39},"\u002F\u002F   ref: null,\n",[33,242,244],{"class":35,"line":243},22,[33,245,246],{"class":39},"\u002F\u002F   $$typeof: Symbol.for('react.element')\n",[33,248,250],{"class":35,"line":249},23,[33,251,252],{"class":39},"\u002F\u002F }\n",[33,254,256],{"class":35,"line":255},24,[33,257,53],{"emptyLinePlaceholder":52},[33,259,261],{"class":35,"line":260},25,[33,262,263],{"class":39},"\u002F\u002F Knowing this explains WHY:\n",[33,265,267],{"class":35,"line":266},26,[33,268,269],{"class":39},"\u002F\u002F - You can store JSX in variables: const el = \u003Cdiv\u002F>  (it's just an object)\n",[33,271,273],{"class":35,"line":272},27,[33,274,275],{"class":39},"\u002F\u002F - You can pass JSX as props: \u003CCard header={\u003Ch1>Title\u003C\u002Fh1>} \u002F>\n",[33,277,279],{"class":35,"line":278},28,[33,280,281],{"class":39},"\u002F\u002F - You can return JSX from functions: getIcon(name) → \u003Csvg\u002F>\n",[33,283,285],{"class":35,"line":284},29,[33,286,287],{"class":39},"\u002F\u002F - You can't use if\u002Ffor\u002Fswitch INSIDE JSX — they're statements, not expressions\n",[14,289,291],{"id":290},"expression-embedding-rules","Expression Embedding Rules",[19,293,295],{"filename":294,"language":22},"expression_embedding.js",[24,296,298],{"className":26,"code":297,"language":22,"meta":28,"style":28},"\u002F\u002F {} in JSX evaluates a SINGLE EXPRESSION — anything that returns a value.\n\u002F\u002F You CANNOT put STATEMENTS (if, for, switch, const) inside {}.\n\n\u002F\u002F VALID — expressions:\n\u003Cdiv>{2 + 2}\u003C\u002Fdiv>                    \u002F\u002F arithmetic\n\u003Cdiv>{condition ? 'yes' : 'no'}\u003C\u002Fdiv>  \u002F\u002F ternary\n\u003Cdiv>{user?.name || 'Anonymous'}\u003C\u002Fdiv> \u002F\u002F optional chaining + fallback\n\u003Cdiv>{items.map(i => \u003Cli key={i.id}>{i.name}\u003C\u002Fli>)}\u003C\u002Fdiv>  \u002F\u002F .map() returns array\n\u003Cdiv>{\u003CChild \u002F>}\u003C\u002Fdiv>                 \u002F\u002F JSX is an expression (it's just an object)\n\n\u002F\u002F INVALID — statements (these throw syntax errors):\n\u002F\u002F \u003Cdiv>{ if (x) { return 'yes' } }\u003C\u002Fdiv>          \u002F\u002F if is a statement\n\u002F\u002F \u003Cdiv>{ for (let i of items) { ... } }\u003C\u002Fdiv>     \u002F\u002F for is a statement\n\u002F\u002F \u003Cdiv>{ const val = compute(); val }\u003C\u002Fdiv>       \u002F\u002F const is a statement\n\n\u002F\u002F WORKAROUND for conditionals inside JSX: ternary or &&\n\u003Cdiv>{show && \u003CModal\u002F>}\u003C\u002Fdiv>\n\u002F\u002F WORKAROUND for loops: .map() (it returns an array of elements)\n\u003Cdiv>{items.map(item => \u003CRow key={item.id} {...item} \u002F>)}\u003C\u002Fdiv>\n\u002F\u002F WORKAROUND for complex logic: IIFE or extract to a variable\u002Ffunction\nconst content = (() => {\n  if (loading) return \u003CSpinner\u002F>\n  if (error) return \u003CErrorMessage error={error}\u002F>\n  return \u003CDataView data={data}\u002F>\n})()\nreturn \u003Cdiv>{content}\u003C\u002Fdiv>\n",[30,299,300,305,310,314,319,350,381,406,453,476,480,485,493,501,509,513,518,542,547,586,591,609,628,650,668,673],{"__ignoreMap":28},[33,301,302],{"class":35,"line":36},[33,303,304],{"class":39},"\u002F\u002F {} in JSX evaluates a SINGLE EXPRESSION — anything that returns a value.\n",[33,306,307],{"class":35,"line":43},[33,308,309],{"class":39},"\u002F\u002F You CANNOT put STATEMENTS (if, for, switch, const) inside {}.\n",[33,311,312],{"class":35,"line":49},[33,313,53],{"emptyLinePlaceholder":52},[33,315,316],{"class":35,"line":56},[33,317,318],{"class":39},"\u002F\u002F VALID — expressions:\n",[33,320,321,324,327,330,333,336,339,342,344,347],{"class":35,"line":62},[33,322,323],{"class":76},"\u003C",[33,325,326],{"class":80},"div",[33,328,329],{"class":76},">{",[33,331,332],{"class":69},"2",[33,334,335],{"class":65}," +",[33,337,338],{"class":69}," 2",[33,340,341],{"class":76},"}\u003C\u002F",[33,343,326],{"class":80},[33,345,346],{"class":76},">                    ",[33,348,349],{"class":39},"\u002F\u002F arithmetic\n",[33,351,352,354,356,359,362,365,368,371,373,375,378],{"class":35,"line":110},[33,353,323],{"class":76},[33,355,326],{"class":80},[33,357,358],{"class":76},">{condition ",[33,360,361],{"class":65},"?",[33,363,364],{"class":90}," 'yes'",[33,366,367],{"class":65}," :",[33,369,370],{"class":90}," 'no'",[33,372,341],{"class":76},[33,374,326],{"class":80},[33,376,377],{"class":76},">  ",[33,379,380],{"class":39},"\u002F\u002F ternary\n",[33,382,383,385,387,390,393,396,398,400,403],{"class":35,"line":115},[33,384,323],{"class":76},[33,386,326],{"class":80},[33,388,389],{"class":76},">{user?.name ",[33,391,392],{"class":65},"||",[33,394,395],{"class":90}," 'Anonymous'",[33,397,341],{"class":76},[33,399,326],{"class":80},[33,401,402],{"class":76},"> ",[33,404,405],{"class":39},"\u002F\u002F optional chaining + fallback\n",[33,407,408,410,412,415,418,421,425,428,430,433,436,438,441,443,446,448,450],{"class":35,"line":121},[33,409,323],{"class":76},[33,411,326],{"class":80},[33,413,414],{"class":76},">{items.",[33,416,417],{"class":83},"map",[33,419,420],{"class":76},"(",[33,422,424],{"class":423},"sCrzJ","i",[33,426,427],{"class":65}," =>",[33,429,77],{"class":76},[33,431,432],{"class":80},"li",[33,434,435],{"class":83}," key",[33,437,87],{"class":65},[33,439,440],{"class":76},"{i.id}>{i.name}\u003C\u002F",[33,442,432],{"class":80},[33,444,445],{"class":76},">)}\u003C\u002F",[33,447,326],{"class":80},[33,449,377],{"class":76},[33,451,452],{"class":39},"\u002F\u002F .map() returns array\n",[33,454,455,457,459,462,465,468,470,473],{"class":35,"line":139},[33,456,323],{"class":76},[33,458,326],{"class":80},[33,460,461],{"class":76},">{\u003C",[33,463,464],{"class":69},"Child",[33,466,467],{"class":76}," \u002F>}\u003C\u002F",[33,469,326],{"class":80},[33,471,472],{"class":76},">                 ",[33,474,475],{"class":39},"\u002F\u002F JSX is an expression (it's just an object)\n",[33,477,478],{"class":35,"line":151},[33,479,53],{"emptyLinePlaceholder":52},[33,481,482],{"class":35,"line":172},[33,483,484],{"class":39},"\u002F\u002F INVALID — statements (these throw syntax errors):\n",[33,486,487,490],{"class":35,"line":184},[33,488,489],{"class":39},"\u002F\u002F \u003Cdiv>{ if (x) { return 'yes' } }\u003C\u002Fdiv>",[33,491,492],{"class":39},"          \u002F\u002F if is a statement\n",[33,494,495,498],{"class":35,"line":190},[33,496,497],{"class":39},"\u002F\u002F \u003Cdiv>{ for (let i of items) { ... } }\u003C\u002Fdiv>",[33,499,500],{"class":39},"     \u002F\u002F for is a statement\n",[33,502,503,506],{"class":35,"line":196},[33,504,505],{"class":39},"\u002F\u002F \u003Cdiv>{ const val = compute(); val }\u003C\u002Fdiv>",[33,507,508],{"class":39},"       \u002F\u002F const is a statement\n",[33,510,511],{"class":35,"line":202},[33,512,53],{"emptyLinePlaceholder":52},[33,514,515],{"class":35,"line":207},[33,516,517],{"class":39},"\u002F\u002F WORKAROUND for conditionals inside JSX: ternary or &&\n",[33,519,520,522,524,527,530,532,535,538,540],{"class":35,"line":213},[33,521,323],{"class":76},[33,523,326],{"class":80},[33,525,526],{"class":76},">{show ",[33,528,529],{"class":65},"&&",[33,531,77],{"class":76},[33,533,534],{"class":69},"Modal",[33,536,537],{"class":76},"\u002F>}\u003C\u002F",[33,539,326],{"class":80},[33,541,107],{"class":76},[33,543,544],{"class":35,"line":219},[33,545,546],{"class":39},"\u002F\u002F WORKAROUND for loops: .map() (it returns an array of elements)\n",[33,548,549,551,553,555,557,559,562,564,566,569,571,573,576,579,582,584],{"class":35,"line":225},[33,550,323],{"class":76},[33,552,326],{"class":80},[33,554,414],{"class":76},[33,556,417],{"class":83},[33,558,420],{"class":76},[33,560,561],{"class":423},"item",[33,563,427],{"class":65},[33,565,77],{"class":76},[33,567,568],{"class":69},"Row",[33,570,435],{"class":83},[33,572,87],{"class":65},[33,574,575],{"class":76},"{item.id} {",[33,577,578],{"class":65},"...",[33,580,581],{"class":76},"item} \u002F>)}\u003C\u002F",[33,583,326],{"class":80},[33,585,107],{"class":76},[33,587,588],{"class":35,"line":231},[33,589,590],{"class":39},"\u002F\u002F WORKAROUND for complex logic: IIFE or extract to a variable\u002Ffunction\n",[33,592,593,595,598,600,603,606],{"class":35,"line":237},[33,594,66],{"class":65},[33,596,597],{"class":69}," content",[33,599,73],{"class":65},[33,601,602],{"class":76}," (() ",[33,604,605],{"class":65},"=>",[33,607,608],{"class":76}," {\n",[33,610,611,614,617,620,622,625],{"class":35,"line":243},[33,612,613],{"class":65},"  if",[33,615,616],{"class":76}," (loading) ",[33,618,619],{"class":65},"return",[33,621,77],{"class":76},[33,623,624],{"class":69},"Spinner",[33,626,627],{"class":76},"\u002F>\n",[33,629,630,632,635,637,639,642,645,647],{"class":35,"line":249},[33,631,613],{"class":65},[33,633,634],{"class":76}," (error) ",[33,636,619],{"class":65},[33,638,77],{"class":76},[33,640,641],{"class":69},"ErrorMessage",[33,643,644],{"class":83}," error",[33,646,87],{"class":65},[33,648,649],{"class":76},"{error}\u002F>\n",[33,651,652,655,657,660,663,665],{"class":35,"line":255},[33,653,654],{"class":65},"  return",[33,656,77],{"class":76},[33,658,659],{"class":69},"DataView",[33,661,662],{"class":83}," data",[33,664,87],{"class":65},[33,666,667],{"class":76},"{data}\u002F>\n",[33,669,670],{"class":35,"line":260},[33,671,672],{"class":76},"})()\n",[33,674,675,677,679,681,684,686],{"class":35,"line":266},[33,676,619],{"class":65},[33,678,77],{"class":76},[33,680,326],{"class":80},[33,682,683],{"class":76},">{content}\u003C\u002F",[33,685,326],{"class":80},[33,687,107],{"class":76},[14,689,691],{"id":690},"conditional-rendering-patterns-and-gotchas","Conditional Rendering: Patterns and Gotchas",[19,693,695],{"filename":694,"language":22},"conditional_gotchas.js",[24,696,698],{"className":26,"code":697,"language":22,"meta":28,"style":28},"\u002F\u002F ANTI-PATTERN: && with numeric values renders 0\nfunction Cart({ count }) {\n  return \u003Cdiv>{count && \u003CBadge count={count} \u002F>}\u003C\u002Fdiv>\n  \u002F\u002F When count === 0: renders \"0\" on screen! 0 is falsy but React renders it.\n  \u002F\u002F && returns the LEFT operand if it's falsy — so 0 && \u003CBadge\u002F> → 0\n  \u002F\u002F React renders numbers (including 0) as text. Only null, undefined, false,\n  \u002F\u002F and true are ignored by React's renderer.\n}\n\n\u002F\u002F FIX: use a boolean check or ternary\nfunction Cart({ count }) {\n  return \u003Cdiv>{count > 0 && \u003CBadge count={count} \u002F>}\u003C\u002Fdiv>  \u002F\u002F count > 0 → true\u002Ffalse\n  \u002F\u002F OR: {count > 0 ? \u003CBadge count={count} \u002F> : null}\n}\n\n\u002F\u002F GOTCHA: empty string \"\" is rendered by React (it's a valid child)\n\u002F\u002F null, undefined, false, true → NOT rendered (ignored)\n\u002F\u002F 0, \"\" → rendered as text\n",[30,699,700,705,722,752,757,762,767,772,777,781,786,798,834,839,843,847,852,857],{"__ignoreMap":28},[33,701,702],{"class":35,"line":36},[33,703,704],{"class":39},"\u002F\u002F ANTI-PATTERN: && with numeric values renders 0\n",[33,706,707,710,713,716,719],{"class":35,"line":43},[33,708,709],{"class":65},"function",[33,711,712],{"class":83}," Cart",[33,714,715],{"class":76},"({ ",[33,717,718],{"class":423},"count",[33,720,721],{"class":76}," }) {\n",[33,723,724,726,728,730,733,735,737,740,743,745,748,750],{"class":35,"line":49},[33,725,654],{"class":65},[33,727,77],{"class":76},[33,729,326],{"class":80},[33,731,732],{"class":76},">{count ",[33,734,529],{"class":65},[33,736,77],{"class":76},[33,738,739],{"class":69},"Badge",[33,741,742],{"class":83}," count",[33,744,87],{"class":65},[33,746,747],{"class":76},"{count} \u002F>}\u003C\u002F",[33,749,326],{"class":80},[33,751,107],{"class":76},[33,753,754],{"class":35,"line":56},[33,755,756],{"class":39},"  \u002F\u002F When count === 0: renders \"0\" on screen! 0 is falsy but React renders it.\n",[33,758,759],{"class":35,"line":62},[33,760,761],{"class":39},"  \u002F\u002F && returns the LEFT operand if it's falsy — so 0 && \u003CBadge\u002F> → 0\n",[33,763,764],{"class":35,"line":110},[33,765,766],{"class":39},"  \u002F\u002F React renders numbers (including 0) as text. Only null, undefined, false,\n",[33,768,769],{"class":35,"line":115},[33,770,771],{"class":39},"  \u002F\u002F and true are ignored by React's renderer.\n",[33,773,774],{"class":35,"line":121},[33,775,776],{"class":76},"}\n",[33,778,779],{"class":35,"line":139},[33,780,53],{"emptyLinePlaceholder":52},[33,782,783],{"class":35,"line":151},[33,784,785],{"class":39},"\u002F\u002F FIX: use a boolean check or ternary\n",[33,787,788,790,792,794,796],{"class":35,"line":172},[33,789,709],{"class":65},[33,791,712],{"class":83},[33,793,715],{"class":76},[33,795,718],{"class":423},[33,797,721],{"class":76},[33,799,800,802,804,806,808,811,814,817,819,821,823,825,827,829,831],{"class":35,"line":184},[33,801,654],{"class":65},[33,803,77],{"class":76},[33,805,326],{"class":80},[33,807,732],{"class":76},[33,809,810],{"class":65},">",[33,812,813],{"class":69}," 0",[33,815,816],{"class":65}," &&",[33,818,77],{"class":76},[33,820,739],{"class":69},[33,822,742],{"class":83},[33,824,87],{"class":65},[33,826,747],{"class":76},[33,828,326],{"class":80},[33,830,377],{"class":76},[33,832,833],{"class":39},"\u002F\u002F count > 0 → true\u002Ffalse\n",[33,835,836],{"class":35,"line":190},[33,837,838],{"class":39},"  \u002F\u002F OR: {count > 0 ? \u003CBadge count={count} \u002F> : null}\n",[33,840,841],{"class":35,"line":196},[33,842,776],{"class":76},[33,844,845],{"class":35,"line":202},[33,846,53],{"emptyLinePlaceholder":52},[33,848,849],{"class":35,"line":207},[33,850,851],{"class":39},"\u002F\u002F GOTCHA: empty string \"\" is rendered by React (it's a valid child)\n",[33,853,854],{"class":35,"line":213},[33,855,856],{"class":39},"\u002F\u002F null, undefined, false, true → NOT rendered (ignored)\n",[33,858,859],{"class":35,"line":219},[33,860,861],{"class":39},"\u002F\u002F 0, \"\" → rendered as text\n",[19,863,865],{"filename":864,"language":22},"conditional_patterns.js",[24,866,868],{"className":26,"code":867,"language":22,"meta":28,"style":28},"\u002F\u002F PRODUCTION PATTERN: extract complex conditionals for readability\n\nfunction UserMenu({ user, isLoading, isError }) {\n  \u002F\u002F Each branch is a clean expression — no nested ternaries that are hard to read\n  if (isLoading) return \u003CSpinner \u002F>\n  if (isError) return \u003CErrorMessage \u002F>\n  if (!user) return \u003CLoginButton \u002F>\n\n  return \u003CProfileDropdown user={user} \u002F>\n\n  \u002F\u002F Early returns OUTSIDE JSX are cleaner than nested ternaries INSIDE JSX.\n  \u002F\u002F Use ternaries for simple 2-way choices within JSX, early returns for\n  \u002F\u002F multi-branch or guard-clause logic.\n}\n",[30,869,870,875,879,904,909,925,940,962,966,983,987,992,997,1002],{"__ignoreMap":28},[33,871,872],{"class":35,"line":36},[33,873,874],{"class":39},"\u002F\u002F PRODUCTION PATTERN: extract complex conditionals for readability\n",[33,876,877],{"class":35,"line":43},[33,878,53],{"emptyLinePlaceholder":52},[33,880,881,883,886,888,891,894,897,899,902],{"class":35,"line":49},[33,882,709],{"class":65},[33,884,885],{"class":83}," UserMenu",[33,887,715],{"class":76},[33,889,890],{"class":423},"user",[33,892,893],{"class":76},", ",[33,895,896],{"class":423},"isLoading",[33,898,893],{"class":76},[33,900,901],{"class":423},"isError",[33,903,721],{"class":76},[33,905,906],{"class":35,"line":56},[33,907,908],{"class":39},"  \u002F\u002F Each branch is a clean expression — no nested ternaries that are hard to read\n",[33,910,911,913,916,918,920,922],{"class":35,"line":62},[33,912,613],{"class":65},[33,914,915],{"class":76}," (isLoading) ",[33,917,619],{"class":65},[33,919,77],{"class":76},[33,921,624],{"class":69},[33,923,924],{"class":76}," \u002F>\n",[33,926,927,929,932,934,936,938],{"class":35,"line":110},[33,928,613],{"class":65},[33,930,931],{"class":76}," (isError) ",[33,933,619],{"class":65},[33,935,77],{"class":76},[33,937,641],{"class":69},[33,939,924],{"class":76},[33,941,942,944,947,950,953,955,957,960],{"class":35,"line":115},[33,943,613],{"class":65},[33,945,946],{"class":76}," (",[33,948,949],{"class":65},"!",[33,951,952],{"class":76},"user) ",[33,954,619],{"class":65},[33,956,77],{"class":76},[33,958,959],{"class":69},"LoginButton",[33,961,924],{"class":76},[33,963,964],{"class":35,"line":121},[33,965,53],{"emptyLinePlaceholder":52},[33,967,968,970,972,975,978,980],{"class":35,"line":139},[33,969,654],{"class":65},[33,971,77],{"class":76},[33,973,974],{"class":69},"ProfileDropdown",[33,976,977],{"class":83}," user",[33,979,87],{"class":65},[33,981,982],{"class":76},"{user} \u002F>\n",[33,984,985],{"class":35,"line":151},[33,986,53],{"emptyLinePlaceholder":52},[33,988,989],{"class":35,"line":172},[33,990,991],{"class":39},"  \u002F\u002F Early returns OUTSIDE JSX are cleaner than nested ternaries INSIDE JSX.\n",[33,993,994],{"class":35,"line":184},[33,995,996],{"class":39},"  \u002F\u002F Use ternaries for simple 2-way choices within JSX, early returns for\n",[33,998,999],{"class":35,"line":190},[33,1000,1001],{"class":39},"  \u002F\u002F multi-branch or guard-clause logic.\n",[33,1003,1004],{"class":35,"line":196},[33,1005,776],{"class":76},[14,1007,1009],{"id":1008},"fragments-grouping-without-extra-dom","Fragments: Grouping Without Extra DOM",[19,1011,1013],{"filename":1012,"language":22},"fragments.js",[24,1014,1016],{"className":26,"code":1015,"language":22,"meta":28,"style":28},"import { Fragment } from 'react'\n\n\u002F\u002F PROBLEM: a component must return a single root element, but you don't want\n\u002F\u002F to add an extra \u003Cdiv> that breaks CSS (flexbox\u002Fgrid) or semantics.\n\n\u002F\u002F SHORT SYNTAX (no key support):\nfunction Columns() {\n  return (\n    \u003C>\n      \u003Ctd>Hello\u003C\u002Ftd>\n      \u003Ctd>World\u003C\u002Ftd>\n    \u003C\u002F>\n  )\n}\n\u002F\u002F Compiles to React.createElement(React.Fragment, null, ...)\n\n\u002F\u002F EXPLICIT SYNTAX (supports key — needed in lists):\nfunction DefinitionList({ terms }) {\n  return terms.map(([term, def]) => (\n    \u003CFragment key={term}>\n      \u003Cdt>{term}\u003C\u002Fdt>\n      \u003Cdd>{def}\u003C\u002Fdd>\n    \u003C\u002FFragment>\n  ))\n}\n\u002F\u002F The short \u003C> syntax CANNOT take a key prop — use \u003CFragment key={...}> in lists.\n\u002F\u002F React won't warn about missing keys if you use \u003C> — but it won't be able to\n\u002F\u002F reconcile items correctly either. Always use explicit Fragment with key in lists.\n",[30,1017,1018,1032,1036,1041,1046,1050,1055,1065,1072,1077,1092,1105,1110,1115,1119,1124,1128,1133,1147,1174,1189,1203,1217,1226,1231,1235,1240,1245],{"__ignoreMap":28},[33,1019,1020,1023,1026,1029],{"class":35,"line":36},[33,1021,1022],{"class":65},"import",[33,1024,1025],{"class":76}," { Fragment } ",[33,1027,1028],{"class":65},"from",[33,1030,1031],{"class":90}," 'react'\n",[33,1033,1034],{"class":35,"line":43},[33,1035,53],{"emptyLinePlaceholder":52},[33,1037,1038],{"class":35,"line":49},[33,1039,1040],{"class":39},"\u002F\u002F PROBLEM: a component must return a single root element, but you don't want\n",[33,1042,1043],{"class":35,"line":56},[33,1044,1045],{"class":39},"\u002F\u002F to add an extra \u003Cdiv> that breaks CSS (flexbox\u002Fgrid) or semantics.\n",[33,1047,1048],{"class":35,"line":62},[33,1049,53],{"emptyLinePlaceholder":52},[33,1051,1052],{"class":35,"line":110},[33,1053,1054],{"class":39},"\u002F\u002F SHORT SYNTAX (no key support):\n",[33,1056,1057,1059,1062],{"class":35,"line":115},[33,1058,709],{"class":65},[33,1060,1061],{"class":83}," Columns",[33,1063,1064],{"class":76},"() {\n",[33,1066,1067,1069],{"class":35,"line":121},[33,1068,654],{"class":65},[33,1070,1071],{"class":76}," (\n",[33,1073,1074],{"class":35,"line":139},[33,1075,1076],{"class":76},"    \u003C>\n",[33,1078,1079,1082,1085,1088,1090],{"class":35,"line":151},[33,1080,1081],{"class":76},"      \u003C",[33,1083,1084],{"class":80},"td",[33,1086,1087],{"class":76},">Hello\u003C\u002F",[33,1089,1084],{"class":80},[33,1091,107],{"class":76},[33,1093,1094,1096,1098,1101,1103],{"class":35,"line":172},[33,1095,1081],{"class":76},[33,1097,1084],{"class":80},[33,1099,1100],{"class":76},">World\u003C\u002F",[33,1102,1084],{"class":80},[33,1104,107],{"class":76},[33,1106,1107],{"class":35,"line":184},[33,1108,1109],{"class":76},"    \u003C\u002F>\n",[33,1111,1112],{"class":35,"line":190},[33,1113,1114],{"class":76},"  )\n",[33,1116,1117],{"class":35,"line":196},[33,1118,776],{"class":76},[33,1120,1121],{"class":35,"line":202},[33,1122,1123],{"class":39},"\u002F\u002F Compiles to React.createElement(React.Fragment, null, ...)\n",[33,1125,1126],{"class":35,"line":207},[33,1127,53],{"emptyLinePlaceholder":52},[33,1129,1130],{"class":35,"line":213},[33,1131,1132],{"class":39},"\u002F\u002F EXPLICIT SYNTAX (supports key — needed in lists):\n",[33,1134,1135,1137,1140,1142,1145],{"class":35,"line":219},[33,1136,709],{"class":65},[33,1138,1139],{"class":83}," DefinitionList",[33,1141,715],{"class":76},[33,1143,1144],{"class":423},"terms",[33,1146,721],{"class":76},[33,1148,1149,1151,1154,1156,1159,1162,1164,1167,1170,1172],{"class":35,"line":225},[33,1150,654],{"class":65},[33,1152,1153],{"class":76}," terms.",[33,1155,417],{"class":83},[33,1157,1158],{"class":76},"(([",[33,1160,1161],{"class":423},"term",[33,1163,893],{"class":76},[33,1165,1166],{"class":423},"def",[33,1168,1169],{"class":76},"]) ",[33,1171,605],{"class":65},[33,1173,1071],{"class":76},[33,1175,1176,1179,1182,1184,1186],{"class":35,"line":231},[33,1177,1178],{"class":76},"    \u003C",[33,1180,1181],{"class":69},"Fragment",[33,1183,435],{"class":83},[33,1185,87],{"class":65},[33,1187,1188],{"class":76},"{term}>\n",[33,1190,1191,1193,1196,1199,1201],{"class":35,"line":237},[33,1192,1081],{"class":76},[33,1194,1195],{"class":80},"dt",[33,1197,1198],{"class":76},">{term}\u003C\u002F",[33,1200,1195],{"class":80},[33,1202,107],{"class":76},[33,1204,1205,1207,1210,1213,1215],{"class":35,"line":243},[33,1206,1081],{"class":76},[33,1208,1209],{"class":80},"dd",[33,1211,1212],{"class":76},">{def}\u003C\u002F",[33,1214,1209],{"class":80},[33,1216,107],{"class":76},[33,1218,1219,1222,1224],{"class":35,"line":249},[33,1220,1221],{"class":76},"    \u003C\u002F",[33,1223,1181],{"class":69},[33,1225,107],{"class":76},[33,1227,1228],{"class":35,"line":255},[33,1229,1230],{"class":76},"  ))\n",[33,1232,1233],{"class":35,"line":260},[33,1234,776],{"class":76},[33,1236,1237],{"class":35,"line":266},[33,1238,1239],{"class":39},"\u002F\u002F The short \u003C> syntax CANNOT take a key prop — use \u003CFragment key={...}> in lists.\n",[33,1241,1242],{"class":35,"line":272},[33,1243,1244],{"class":39},"\u002F\u002F React won't warn about missing keys if you use \u003C> — but it won't be able to\n",[33,1246,1247],{"class":35,"line":278},[33,1248,1249],{"class":39},"\u002F\u002F reconcile items correctly either. Always use explicit Fragment with key in lists.\n",[14,1251,1253],{"id":1252},"spread-attributes-powerful-dangerous","Spread Attributes: Powerful, Dangerous",[19,1255,1257],{"filename":1256,"language":22},"spread_pitfalls.js",[24,1258,1260],{"className":26,"code":1259,"language":22,"meta":28,"style":28},"\u002F\u002F CONVENIENT: forward all props to a child\nfunction Button({ variant, ...rest }) {\n  return \u003Cbutton className={`btn btn-${variant}`} {...rest} \u002F>\n  \u002F\u002F rest = all props except variant — className, onClick, disabled, type, etc.\n}\n\n\u002F\u002F ANTI-PATTERN: spreading unknown props breaks explicit contracts\nfunction UserCard({ name, email, ...unknownProps }) {\n  \u002F\u002F unknownProps could contain ANYTHING — including props UserCard shouldn't receive\n  return \u003Cdiv {...unknownProps}>  \u002F\u002F ← div now has arbitrary attributes\n    \u003Ch3>{name}\u003C\u002Fh3>\n    \u003Cp>{email}\u003C\u002Fp>\n  \u003C\u002Fdiv>\n}\n\u002F\u002F If someone passes \u003CUserCard onClick={...} \u002F>, the div gets an onClick —\n\u002F\u002F probably not intended. Explicit is safer:\nfunction UserCard({ name, email, onClick }) {\n  return \u003Cdiv onClick={onClick}>...\u003C\u002Fdiv>  \u002F\u002F only what you intend\n}\n\n\u002F\u002F GOTCHA: spread overrides earlier props — order matters\n\u003Cinput type=\"text\" {...props} \u002F>  \u002F\u002F props.type overrides \"text\" if present\n\u003Cinput {...props} type=\"text\" \u002F>  \u002F\u002F type=\"text\" always wins (last wins)\n",[30,1261,1262,1267,1288,1320,1325,1329,1333,1338,1364,1369,1385,1399,1413,1422,1426,1431,1436,1457,1480,1484,1488,1493,1518],{"__ignoreMap":28},[33,1263,1264],{"class":35,"line":36},[33,1265,1266],{"class":39},"\u002F\u002F CONVENIENT: forward all props to a child\n",[33,1268,1269,1271,1274,1276,1279,1281,1283,1286],{"class":35,"line":43},[33,1270,709],{"class":65},[33,1272,1273],{"class":83}," Button",[33,1275,715],{"class":76},[33,1277,1278],{"class":423},"variant",[33,1280,893],{"class":76},[33,1282,578],{"class":65},[33,1284,1285],{"class":423},"rest",[33,1287,721],{"class":76},[33,1289,1290,1292,1294,1297,1299,1301,1304,1307,1309,1312,1315,1317],{"class":35,"line":49},[33,1291,654],{"class":65},[33,1293,77],{"class":76},[33,1295,1296],{"class":80},"button",[33,1298,84],{"class":83},[33,1300,87],{"class":65},[33,1302,1303],{"class":76},"{",[33,1305,1306],{"class":90},"`btn btn-${",[33,1308,1278],{"class":76},[33,1310,1311],{"class":90},"}`",[33,1313,1314],{"class":76},"} {",[33,1316,578],{"class":65},[33,1318,1319],{"class":76},"rest} \u002F>\n",[33,1321,1322],{"class":35,"line":56},[33,1323,1324],{"class":39},"  \u002F\u002F rest = all props except variant — className, onClick, disabled, type, etc.\n",[33,1326,1327],{"class":35,"line":62},[33,1328,776],{"class":76},[33,1330,1331],{"class":35,"line":110},[33,1332,53],{"emptyLinePlaceholder":52},[33,1334,1335],{"class":35,"line":115},[33,1336,1337],{"class":39},"\u002F\u002F ANTI-PATTERN: spreading unknown props breaks explicit contracts\n",[33,1339,1340,1342,1345,1347,1350,1352,1355,1357,1359,1362],{"class":35,"line":121},[33,1341,709],{"class":65},[33,1343,1344],{"class":83}," UserCard",[33,1346,715],{"class":76},[33,1348,1349],{"class":423},"name",[33,1351,893],{"class":76},[33,1353,1354],{"class":423},"email",[33,1356,893],{"class":76},[33,1358,578],{"class":65},[33,1360,1361],{"class":423},"unknownProps",[33,1363,721],{"class":76},[33,1365,1366],{"class":35,"line":139},[33,1367,1368],{"class":39},"  \u002F\u002F unknownProps could contain ANYTHING — including props UserCard shouldn't receive\n",[33,1370,1371,1373,1375,1377,1380,1382],{"class":35,"line":151},[33,1372,654],{"class":65},[33,1374,77],{"class":76},[33,1376,326],{"class":80},[33,1378,1379],{"class":76}," {",[33,1381,578],{"class":65},[33,1383,1384],{"class":76},"unknownProps}>  \u002F\u002F ← div now has arbitrary attributes\n",[33,1386,1387,1389,1392,1395,1397],{"class":35,"line":172},[33,1388,1178],{"class":76},[33,1390,1391],{"class":80},"h3",[33,1393,1394],{"class":76},">{name}\u003C\u002F",[33,1396,1391],{"class":80},[33,1398,107],{"class":76},[33,1400,1401,1403,1406,1409,1411],{"class":35,"line":184},[33,1402,1178],{"class":76},[33,1404,1405],{"class":80},"p",[33,1407,1408],{"class":76},">{email}\u003C\u002F",[33,1410,1405],{"class":80},[33,1412,107],{"class":76},[33,1414,1415,1418,1420],{"class":35,"line":190},[33,1416,1417],{"class":76},"  \u003C\u002F",[33,1419,326],{"class":80},[33,1421,107],{"class":76},[33,1423,1424],{"class":35,"line":196},[33,1425,776],{"class":76},[33,1427,1428],{"class":35,"line":202},[33,1429,1430],{"class":39},"\u002F\u002F If someone passes \u003CUserCard onClick={...} \u002F>, the div gets an onClick —\n",[33,1432,1433],{"class":35,"line":207},[33,1434,1435],{"class":39},"\u002F\u002F probably not intended. Explicit is safer:\n",[33,1437,1438,1440,1442,1444,1446,1448,1450,1452,1455],{"class":35,"line":213},[33,1439,709],{"class":65},[33,1441,1344],{"class":83},[33,1443,715],{"class":76},[33,1445,1349],{"class":423},[33,1447,893],{"class":76},[33,1449,1354],{"class":423},[33,1451,893],{"class":76},[33,1453,1454],{"class":423},"onClick",[33,1456,721],{"class":76},[33,1458,1459,1461,1463,1465,1468,1470,1473,1475,1477],{"class":35,"line":219},[33,1460,654],{"class":65},[33,1462,77],{"class":76},[33,1464,326],{"class":80},[33,1466,1467],{"class":83}," onClick",[33,1469,87],{"class":65},[33,1471,1472],{"class":76},"{onClick}>...\u003C\u002F",[33,1474,326],{"class":80},[33,1476,377],{"class":76},[33,1478,1479],{"class":39},"\u002F\u002F only what you intend\n",[33,1481,1482],{"class":35,"line":225},[33,1483,776],{"class":76},[33,1485,1486],{"class":35,"line":231},[33,1487,53],{"emptyLinePlaceholder":52},[33,1489,1490],{"class":35,"line":237},[33,1491,1492],{"class":39},"\u002F\u002F GOTCHA: spread overrides earlier props — order matters\n",[33,1494,1495,1497,1500,1503,1505,1508,1510,1512,1515],{"class":35,"line":243},[33,1496,323],{"class":76},[33,1498,1499],{"class":80},"input",[33,1501,1502],{"class":83}," type",[33,1504,87],{"class":65},[33,1506,1507],{"class":90},"\"text\"",[33,1509,1379],{"class":76},[33,1511,578],{"class":65},[33,1513,1514],{"class":76},"props} \u002F>  ",[33,1516,1517],{"class":39},"\u002F\u002F props.type overrides \"text\" if present\n",[33,1519,1520,1522,1524,1526,1528,1531,1534,1536,1538,1541],{"class":35,"line":249},[33,1521,323],{"class":76},[33,1523,1499],{"class":80},[33,1525,1379],{"class":76},[33,1527,578],{"class":65},[33,1529,1530],{"class":76},"props} ",[33,1532,1533],{"class":83},"type",[33,1535,87],{"class":65},[33,1537,1507],{"class":90},[33,1539,1540],{"class":76}," \u002F>  ",[33,1542,1543],{"class":39},"\u002F\u002F type=\"text\" always wins (last wins)\n",[14,1545,1547],{"id":1546},"inline-object-literals-and-re-render-traps","Inline Object Literals and Re-render Traps",[19,1549,1551],{"filename":1550,"language":22},"inline_object_renders.js",[24,1552,1554],{"className":26,"code":1553,"language":22,"meta":28,"style":28},"\u002F\u002F ANTI-PATTERN: inline object\u002Farray literals create NEW references every render\nfunction Parent({ data }) {\n  return \u003CChild\n    config={{ theme: 'dark', size: 'lg' }}  \u002F\u002F ← new object every render\n    items={[1, 2, 3]}                        \u002F\u002F ← new array every render\n    style={{ color: 'red' }}                 \u002F\u002F ← new object every render\n  \u002F>\n}\n\u002F\u002F If Child is React.memo'd, the memo BREAKS — new object\u002Farray reference every\n\u002F\u002F render means shallow comparison fails, Child re-renders every time.\n\u002F\u002F These literals also break useEffect\u002FuseCallback dependency arrays (Ch 6, 9).\n\n\u002F\u002F FIX: hoist stable references outside the component or use useMemo\nconst STATIC_CONFIG = { theme: 'dark', size: 'lg' }  \u002F\u002F module-level constant\nconst STATIC_ITEMS = [1, 2, 3]\n\nfunction Parent({ data }) {\n  return \u003CChild config={STATIC_CONFIG} items={STATIC_ITEMS} \u002F>\n}\n\u002F\u002F Now the references are stable — React.memo on Child works correctly.\n",[30,1555,1556,1561,1575,1584,1609,1637,1655,1660,1664,1669,1674,1679,1683,1688,1712,1737,1741,1753,1787,1791],{"__ignoreMap":28},[33,1557,1558],{"class":35,"line":36},[33,1559,1560],{"class":39},"\u002F\u002F ANTI-PATTERN: inline object\u002Farray literals create NEW references every render\n",[33,1562,1563,1565,1568,1570,1573],{"class":35,"line":43},[33,1564,709],{"class":65},[33,1566,1567],{"class":83}," Parent",[33,1569,715],{"class":76},[33,1571,1572],{"class":423},"data",[33,1574,721],{"class":76},[33,1576,1577,1579,1581],{"class":35,"line":49},[33,1578,654],{"class":65},[33,1580,77],{"class":76},[33,1582,1583],{"class":69},"Child\n",[33,1585,1586,1589,1591,1594,1597,1600,1603,1606],{"class":35,"line":56},[33,1587,1588],{"class":83},"    config",[33,1590,87],{"class":65},[33,1592,1593],{"class":76},"{{ theme: ",[33,1595,1596],{"class":90},"'dark'",[33,1598,1599],{"class":76},", size: ",[33,1601,1602],{"class":90},"'lg'",[33,1604,1605],{"class":76}," }}  ",[33,1607,1608],{"class":39},"\u002F\u002F ← new object every render\n",[33,1610,1611,1614,1616,1619,1622,1624,1626,1628,1631,1634],{"class":35,"line":62},[33,1612,1613],{"class":83},"    items",[33,1615,87],{"class":65},[33,1617,1618],{"class":76},"{[",[33,1620,1621],{"class":69},"1",[33,1623,893],{"class":76},[33,1625,332],{"class":69},[33,1627,893],{"class":76},[33,1629,1630],{"class":69},"3",[33,1632,1633],{"class":76},"]}                        ",[33,1635,1636],{"class":39},"\u002F\u002F ← new array every render\n",[33,1638,1639,1642,1644,1647,1650,1653],{"class":35,"line":110},[33,1640,1641],{"class":83},"    style",[33,1643,87],{"class":65},[33,1645,1646],{"class":76},"{{ color: ",[33,1648,1649],{"class":90},"'red'",[33,1651,1652],{"class":76}," }}                 ",[33,1654,1608],{"class":39},[33,1656,1657],{"class":35,"line":115},[33,1658,1659],{"class":76},"  \u002F>\n",[33,1661,1662],{"class":35,"line":121},[33,1663,776],{"class":76},[33,1665,1666],{"class":35,"line":139},[33,1667,1668],{"class":39},"\u002F\u002F If Child is React.memo'd, the memo BREAKS — new object\u002Farray reference every\n",[33,1670,1671],{"class":35,"line":151},[33,1672,1673],{"class":39},"\u002F\u002F render means shallow comparison fails, Child re-renders every time.\n",[33,1675,1676],{"class":35,"line":172},[33,1677,1678],{"class":39},"\u002F\u002F These literals also break useEffect\u002FuseCallback dependency arrays (Ch 6, 9).\n",[33,1680,1681],{"class":35,"line":184},[33,1682,53],{"emptyLinePlaceholder":52},[33,1684,1685],{"class":35,"line":190},[33,1686,1687],{"class":39},"\u002F\u002F FIX: hoist stable references outside the component or use useMemo\n",[33,1689,1690,1692,1695,1697,1700,1702,1704,1706,1709],{"class":35,"line":196},[33,1691,66],{"class":65},[33,1693,1694],{"class":69}," STATIC_CONFIG",[33,1696,73],{"class":65},[33,1698,1699],{"class":76}," { theme: ",[33,1701,1596],{"class":90},[33,1703,1599],{"class":76},[33,1705,1602],{"class":90},[33,1707,1708],{"class":76}," }  ",[33,1710,1711],{"class":39},"\u002F\u002F module-level constant\n",[33,1713,1714,1716,1719,1721,1724,1726,1728,1730,1732,1734],{"class":35,"line":202},[33,1715,66],{"class":65},[33,1717,1718],{"class":69}," STATIC_ITEMS",[33,1720,73],{"class":65},[33,1722,1723],{"class":76}," [",[33,1725,1621],{"class":69},[33,1727,893],{"class":76},[33,1729,332],{"class":69},[33,1731,893],{"class":76},[33,1733,1630],{"class":69},[33,1735,1736],{"class":76},"]\n",[33,1738,1739],{"class":35,"line":207},[33,1740,53],{"emptyLinePlaceholder":52},[33,1742,1743,1745,1747,1749,1751],{"class":35,"line":213},[33,1744,709],{"class":65},[33,1746,1567],{"class":83},[33,1748,715],{"class":76},[33,1750,1572],{"class":423},[33,1752,721],{"class":76},[33,1754,1755,1757,1759,1761,1764,1766,1768,1771,1774,1777,1779,1781,1784],{"class":35,"line":219},[33,1756,654],{"class":65},[33,1758,77],{"class":76},[33,1760,464],{"class":69},[33,1762,1763],{"class":83}," config",[33,1765,87],{"class":65},[33,1767,1303],{"class":76},[33,1769,1770],{"class":69},"STATIC_CONFIG",[33,1772,1773],{"class":76},"} ",[33,1775,1776],{"class":83},"items",[33,1778,87],{"class":65},[33,1780,1303],{"class":76},[33,1782,1783],{"class":69},"STATIC_ITEMS",[33,1785,1786],{"class":76},"} \u002F>\n",[33,1788,1789],{"class":35,"line":225},[33,1790,776],{"class":76},[33,1792,1793],{"class":35,"line":231},[33,1794,1795],{"class":39},"\u002F\u002F Now the references are stable — React.memo on Child works correctly.\n",[14,1797,1799],{"id":1798},"tips-tricks","💡 Tips & Tricks",[19,1801,1803],{"filename":1802,"language":22},"tips.js",[24,1804,1806],{"className":26,"code":1805,"language":22,"meta":28,"style":28},"\u002F\u002F [Idiom] JSX is just an object — you can store it, pass it, return it from\n\u002F\u002F functions. Use this to build render helpers without creating components:\n\u002F\u002F const icon = isLoading ? \u003CSpinner\u002F> : \u003CCheckIcon\u002F>\n\n\u002F\u002F [Idiom] Use early returns for guard clauses instead of deep nesting.\n\u002F\u002F if (!data) return null is cleaner than {data && \u003Cdiv>...\u003C\u002Fdiv>} for multi-line.\n\n\u002F\u002F [Performance] Hoist stable object\u002Farray literals to module scope to avoid\n\u002F\u002F breaking React.memo on children. Every inline {{...}} creates a new reference.\n\n\u002F\u002F [Debug] If a number \"0\" appears unexpectedly in your UI, check for\n\u002F\u002F {count && \u003CComponent\u002F>} — use {count > 0 && \u003CComponent\u002F>} instead.\n\n\u002F\u002F [Idiom] \u003CFragment key={...}> is required when mapping to multiple sibling\n\u002F\u002F elements per item. The short \u003C> syntax can't take a key.\n",[30,1807,1808,1813,1818,1823,1827,1832,1837,1841,1846,1851,1855,1860,1865,1869,1874],{"__ignoreMap":28},[33,1809,1810],{"class":35,"line":36},[33,1811,1812],{"class":39},"\u002F\u002F [Idiom] JSX is just an object — you can store it, pass it, return it from\n",[33,1814,1815],{"class":35,"line":43},[33,1816,1817],{"class":39},"\u002F\u002F functions. Use this to build render helpers without creating components:\n",[33,1819,1820],{"class":35,"line":49},[33,1821,1822],{"class":39},"\u002F\u002F const icon = isLoading ? \u003CSpinner\u002F> : \u003CCheckIcon\u002F>\n",[33,1824,1825],{"class":35,"line":56},[33,1826,53],{"emptyLinePlaceholder":52},[33,1828,1829],{"class":35,"line":62},[33,1830,1831],{"class":39},"\u002F\u002F [Idiom] Use early returns for guard clauses instead of deep nesting.\n",[33,1833,1834],{"class":35,"line":110},[33,1835,1836],{"class":39},"\u002F\u002F if (!data) return null is cleaner than {data && \u003Cdiv>...\u003C\u002Fdiv>} for multi-line.\n",[33,1838,1839],{"class":35,"line":115},[33,1840,53],{"emptyLinePlaceholder":52},[33,1842,1843],{"class":35,"line":121},[33,1844,1845],{"class":39},"\u002F\u002F [Performance] Hoist stable object\u002Farray literals to module scope to avoid\n",[33,1847,1848],{"class":35,"line":139},[33,1849,1850],{"class":39},"\u002F\u002F breaking React.memo on children. Every inline {{...}} creates a new reference.\n",[33,1852,1853],{"class":35,"line":151},[33,1854,53],{"emptyLinePlaceholder":52},[33,1856,1857],{"class":35,"line":172},[33,1858,1859],{"class":39},"\u002F\u002F [Debug] If a number \"0\" appears unexpectedly in your UI, check for\n",[33,1861,1862],{"class":35,"line":184},[33,1863,1864],{"class":39},"\u002F\u002F {count && \u003CComponent\u002F>} — use {count > 0 && \u003CComponent\u002F>} instead.\n",[33,1866,1867],{"class":35,"line":190},[33,1868,53],{"emptyLinePlaceholder":52},[33,1870,1871],{"class":35,"line":196},[33,1872,1873],{"class":39},"\u002F\u002F [Idiom] \u003CFragment key={...}> is required when mapping to multiple sibling\n",[33,1875,1876],{"class":35,"line":202},[33,1877,1878],{"class":39},"\u002F\u002F elements per item. The short \u003C> syntax can't take a key.\n",[14,1880,1882],{"id":1881},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[19,1884,1886],{"filename":1885,"language":22},"edge_cases.js",[24,1887,1889],{"className":26,"code":1888,"language":22,"meta":28,"style":28},"\u002F\u002F [Gotcha] && with 0 renders \"0\" on screen. 0 is falsy but React renders numbers.\n\u002F\u002F Fix: {count > 0 && \u003CBadge\u002F>} or {count ? \u003CBadge\u002F> : null}\n\n\u002F\u002F [Gotcha] Empty string \"\" is rendered by React. null, undefined, false, true\n\u002F\u002F are NOT rendered. If you conditionally render an empty string for \"hide\",\n\u002F\u002F it still takes up space in some layouts. Use null instead.\n\n\u002F\u002F [Gotcha] Spread {...props} overrides earlier explicit props if it comes AFTER\n\u002F\u002F them. Put spread FIRST if you want explicit props to win, LAST if spread wins.\n\n\u002F\u002F [Gotcha] You can't use if\u002Ffor\u002Fwhile\u002Fswitch inside {} — they're statements.\n\u002F\u002F Use ternary, &&, .map(), or extract to a variable\u002Ffunction.\n\n\u002F\u002F [Gotcha] JSX comments ({\u002F* *\u002F}) are NOT regular HTML comments (\u003C!-- -->).\n\u002F\u002F HTML comments inside JSX are treated as text and rendered to the DOM.\n\u002F\u002F Always use {\u002F* comment *\u002F} for JSX comments.\n",[30,1890,1891,1896,1901,1905,1910,1915,1920,1924,1929,1934,1938,1943,1948,1952,1957,1962],{"__ignoreMap":28},[33,1892,1893],{"class":35,"line":36},[33,1894,1895],{"class":39},"\u002F\u002F [Gotcha] && with 0 renders \"0\" on screen. 0 is falsy but React renders numbers.\n",[33,1897,1898],{"class":35,"line":43},[33,1899,1900],{"class":39},"\u002F\u002F Fix: {count > 0 && \u003CBadge\u002F>} or {count ? \u003CBadge\u002F> : null}\n",[33,1902,1903],{"class":35,"line":49},[33,1904,53],{"emptyLinePlaceholder":52},[33,1906,1907],{"class":35,"line":56},[33,1908,1909],{"class":39},"\u002F\u002F [Gotcha] Empty string \"\" is rendered by React. null, undefined, false, true\n",[33,1911,1912],{"class":35,"line":62},[33,1913,1914],{"class":39},"\u002F\u002F are NOT rendered. If you conditionally render an empty string for \"hide\",\n",[33,1916,1917],{"class":35,"line":110},[33,1918,1919],{"class":39},"\u002F\u002F it still takes up space in some layouts. Use null instead.\n",[33,1921,1922],{"class":35,"line":115},[33,1923,53],{"emptyLinePlaceholder":52},[33,1925,1926],{"class":35,"line":121},[33,1927,1928],{"class":39},"\u002F\u002F [Gotcha] Spread {...props} overrides earlier explicit props if it comes AFTER\n",[33,1930,1931],{"class":35,"line":139},[33,1932,1933],{"class":39},"\u002F\u002F them. Put spread FIRST if you want explicit props to win, LAST if spread wins.\n",[33,1935,1936],{"class":35,"line":151},[33,1937,53],{"emptyLinePlaceholder":52},[33,1939,1940],{"class":35,"line":172},[33,1941,1942],{"class":39},"\u002F\u002F [Gotcha] You can't use if\u002Ffor\u002Fwhile\u002Fswitch inside {} — they're statements.\n",[33,1944,1945],{"class":35,"line":184},[33,1946,1947],{"class":39},"\u002F\u002F Use ternary, &&, .map(), or extract to a variable\u002Ffunction.\n",[33,1949,1950],{"class":35,"line":190},[33,1951,53],{"emptyLinePlaceholder":52},[33,1953,1954],{"class":35,"line":196},[33,1955,1956],{"class":39},"\u002F\u002F [Gotcha] JSX comments ({\u002F* *\u002F}) are NOT regular HTML comments (\u003C!-- -->).\n",[33,1958,1959],{"class":35,"line":202},[33,1960,1961],{"class":39},"\u002F\u002F HTML comments inside JSX are treated as text and rendered to the DOM.\n",[33,1963,1964],{"class":35,"line":207},[33,1965,1966],{"class":39},"\u002F\u002F Always use {\u002F* comment *\u002F} for JSX comments.\n",[14,1968,1970],{"id":1969},"spot-the-bug","🧠 Spot the Bug",[1405,1972,1973],{},"A developer renders a list of products but sees a React warning: \"Each child in a list should have a unique key prop.\" The code looks correct:",[19,1975,1977],{"filename":1976,"language":22},"spot_the_bug.js",[24,1978,1980],{"className":26,"code":1979,"language":22,"meta":28,"style":28},"function ProductList({ products }) {\n  return (\n    \u003Cdiv>\n      {products.map(product => (\n        \u003C>\n          \u003Ch3>{product.name}\u003C\u002Fh3>\n          \u003Cp>{product.price}\u003C\u002Fp>\n        \u003C\u002F>\n      ))}\n    \u003C\u002Fdiv>\n  )\n}\n",[30,1981,1982,1996,2002,2010,2026,2031,2045,2058,2063,2068,2076,2080],{"__ignoreMap":28},[33,1983,1984,1986,1989,1991,1994],{"class":35,"line":36},[33,1985,709],{"class":65},[33,1987,1988],{"class":83}," ProductList",[33,1990,715],{"class":76},[33,1992,1993],{"class":423},"products",[33,1995,721],{"class":76},[33,1997,1998,2000],{"class":35,"line":43},[33,1999,654],{"class":65},[33,2001,1071],{"class":76},[33,2003,2004,2006,2008],{"class":35,"line":49},[33,2005,1178],{"class":76},[33,2007,326],{"class":80},[33,2009,107],{"class":76},[33,2011,2012,2015,2017,2019,2022,2024],{"class":35,"line":56},[33,2013,2014],{"class":76},"      {products.",[33,2016,417],{"class":83},[33,2018,420],{"class":76},[33,2020,2021],{"class":423},"product",[33,2023,427],{"class":65},[33,2025,1071],{"class":76},[33,2027,2028],{"class":35,"line":62},[33,2029,2030],{"class":76},"        \u003C>\n",[33,2032,2033,2036,2038,2041,2043],{"class":35,"line":110},[33,2034,2035],{"class":76},"          \u003C",[33,2037,1391],{"class":80},[33,2039,2040],{"class":76},">{product.name}\u003C\u002F",[33,2042,1391],{"class":80},[33,2044,107],{"class":76},[33,2046,2047,2049,2051,2054,2056],{"class":35,"line":115},[33,2048,2035],{"class":76},[33,2050,1405],{"class":80},[33,2052,2053],{"class":76},">{product.price}\u003C\u002F",[33,2055,1405],{"class":80},[33,2057,107],{"class":76},[33,2059,2060],{"class":35,"line":121},[33,2061,2062],{"class":76},"        \u003C\u002F>\n",[33,2064,2065],{"class":35,"line":139},[33,2066,2067],{"class":76},"      ))}\n",[33,2069,2070,2072,2074],{"class":35,"line":151},[33,2071,1221],{"class":76},[33,2073,326],{"class":80},[33,2075,107],{"class":76},[33,2077,2078],{"class":35,"line":172},[33,2079,1114],{"class":76},[33,2081,2082],{"class":35,"line":184},[33,2083,776],{"class":76},[2085,2086,2087,2091,2111,2237],"details",{},[2088,2089,2090],"summary",{},"Answer",[1405,2092,2093,2094,2097,2098,2106,2107,2110],{},"The fragment uses the short ",[30,2095,2096],{},"\u003C>"," syntax, which ",[2099,2100,2101,2102,2105],"strong",{},"cannot accept a ",[30,2103,2104],{},"key"," prop",". When mapping to fragments, you must use the explicit ",[30,2108,2109],{},"\u003CFragment key={...}>"," form:",[24,2112,2114],{"className":26,"code":2113,"language":22,"meta":28,"style":28},"import { Fragment } from 'react'\n\nfunction ProductList({ products }) {\n  return (\n    \u003Cdiv>\n      {products.map(product => (\n        \u003CFragment key={product.id}>\n          \u003Ch3>{product.name}\u003C\u002Fh3>\n          \u003Cp>{product.price}\u003C\u002Fp>\n        \u003C\u002FFragment>\n      ))}\n    \u003C\u002Fdiv>\n  )\n}\n",[30,2115,2116,2126,2130,2142,2148,2156,2170,2184,2196,2208,2217,2221,2229,2233],{"__ignoreMap":28},[33,2117,2118,2120,2122,2124],{"class":35,"line":36},[33,2119,1022],{"class":65},[33,2121,1025],{"class":76},[33,2123,1028],{"class":65},[33,2125,1031],{"class":90},[33,2127,2128],{"class":35,"line":43},[33,2129,53],{"emptyLinePlaceholder":52},[33,2131,2132,2134,2136,2138,2140],{"class":35,"line":49},[33,2133,709],{"class":65},[33,2135,1988],{"class":83},[33,2137,715],{"class":76},[33,2139,1993],{"class":423},[33,2141,721],{"class":76},[33,2143,2144,2146],{"class":35,"line":56},[33,2145,654],{"class":65},[33,2147,1071],{"class":76},[33,2149,2150,2152,2154],{"class":35,"line":62},[33,2151,1178],{"class":76},[33,2153,326],{"class":80},[33,2155,107],{"class":76},[33,2157,2158,2160,2162,2164,2166,2168],{"class":35,"line":110},[33,2159,2014],{"class":76},[33,2161,417],{"class":83},[33,2163,420],{"class":76},[33,2165,2021],{"class":423},[33,2167,427],{"class":65},[33,2169,1071],{"class":76},[33,2171,2172,2175,2177,2179,2181],{"class":35,"line":115},[33,2173,2174],{"class":76},"        \u003C",[33,2176,1181],{"class":69},[33,2178,435],{"class":83},[33,2180,87],{"class":65},[33,2182,2183],{"class":76},"{product.id}>\n",[33,2185,2186,2188,2190,2192,2194],{"class":35,"line":121},[33,2187,2035],{"class":76},[33,2189,1391],{"class":80},[33,2191,2040],{"class":76},[33,2193,1391],{"class":80},[33,2195,107],{"class":76},[33,2197,2198,2200,2202,2204,2206],{"class":35,"line":139},[33,2199,2035],{"class":76},[33,2201,1405],{"class":80},[33,2203,2053],{"class":76},[33,2205,1405],{"class":80},[33,2207,107],{"class":76},[33,2209,2210,2213,2215],{"class":35,"line":151},[33,2211,2212],{"class":76},"        \u003C\u002F",[33,2214,1181],{"class":69},[33,2216,107],{"class":76},[33,2218,2219],{"class":35,"line":172},[33,2220,2067],{"class":76},[33,2222,2223,2225,2227],{"class":35,"line":184},[33,2224,1221],{"class":76},[33,2226,326],{"class":80},[33,2228,107],{"class":76},[33,2230,2231],{"class":35,"line":190},[33,2232,1114],{"class":76},[33,2234,2235],{"class":35,"line":196},[33,2236,776],{"class":76},[1405,2238,2239,2240,2243],{},"Without a key on the fragment, React can't track which ",[30,2241,2242],{},"\u003Ch3>+\u003Cp>"," pair corresponds to which product during reconciliation — adding\u002Fremoving\u002Freordering products will cause incorrect DOM updates.",[14,2245,2247],{"id":2246},"key-takeaways","Key Takeaways",[19,2249,2251],{"filename":2250,"language":22},"key_takeaways.js",[24,2252,2254],{"className":26,"code":2253,"language":22,"meta":28,"style":28},"\u002F\u002F 1. JSX compiles to React.createElement() → plain element objects. It's an\n\u002F\u002F    expression, so you can store it, pass it, return it from functions.\n\n\u002F\u002F 2. {} evaluates ONE expression — no statements (if\u002Ffor\u002Fswitch). Use ternary,\n\u002F\u002F    &&, .map(), or extract to a variable\u002Ffunction for complex logic.\n\n\u002F\u002F 3. {count && \u003CX\u002F>} renders \"0\" when count is 0 — use {count > 0 && \u003CX\u002F>}.\n\u002F\u002F    React renders 0 and \"\" as text; ignores null, undefined, false, true.\n\n\u002F\u002F 4. Fragments group siblings without extra DOM. Use \u003CFragment key={...}> in\n\u002F\u002F    lists — the short \u003C> syntax can't take a key prop.\n\n\u002F\u002F 5. Inline object\u002Farray literals ({{...}} and {[...]}) create new references\n\u002F\u002F    every render → breaks React.memo, useEffect deps, useCallback deps.\n\u002F\u002F    Hoist stable values to module scope or use useMemo.\n",[30,2255,2256,2261,2266,2270,2275,2280,2284,2289,2294,2298,2303,2308,2312,2317,2322],{"__ignoreMap":28},[33,2257,2258],{"class":35,"line":36},[33,2259,2260],{"class":39},"\u002F\u002F 1. JSX compiles to React.createElement() → plain element objects. It's an\n",[33,2262,2263],{"class":35,"line":43},[33,2264,2265],{"class":39},"\u002F\u002F    expression, so you can store it, pass it, return it from functions.\n",[33,2267,2268],{"class":35,"line":49},[33,2269,53],{"emptyLinePlaceholder":52},[33,2271,2272],{"class":35,"line":56},[33,2273,2274],{"class":39},"\u002F\u002F 2. {} evaluates ONE expression — no statements (if\u002Ffor\u002Fswitch). Use ternary,\n",[33,2276,2277],{"class":35,"line":62},[33,2278,2279],{"class":39},"\u002F\u002F    &&, .map(), or extract to a variable\u002Ffunction for complex logic.\n",[33,2281,2282],{"class":35,"line":110},[33,2283,53],{"emptyLinePlaceholder":52},[33,2285,2286],{"class":35,"line":115},[33,2287,2288],{"class":39},"\u002F\u002F 3. {count && \u003CX\u002F>} renders \"0\" when count is 0 — use {count > 0 && \u003CX\u002F>}.\n",[33,2290,2291],{"class":35,"line":121},[33,2292,2293],{"class":39},"\u002F\u002F    React renders 0 and \"\" as text; ignores null, undefined, false, true.\n",[33,2295,2296],{"class":35,"line":139},[33,2297,53],{"emptyLinePlaceholder":52},[33,2299,2300],{"class":35,"line":151},[33,2301,2302],{"class":39},"\u002F\u002F 4. Fragments group siblings without extra DOM. Use \u003CFragment key={...}> in\n",[33,2304,2305],{"class":35,"line":172},[33,2306,2307],{"class":39},"\u002F\u002F    lists — the short \u003C> syntax can't take a key prop.\n",[33,2309,2310],{"class":35,"line":184},[33,2311,53],{"emptyLinePlaceholder":52},[33,2313,2314],{"class":35,"line":190},[33,2315,2316],{"class":39},"\u002F\u002F 5. Inline object\u002Farray literals ({{...}} and {[...]}) create new references\n",[33,2318,2319],{"class":35,"line":196},[33,2320,2321],{"class":39},"\u002F\u002F    every render → breaks React.memo, useEffect deps, useCallback deps.\n",[33,2323,2324],{"class":35,"line":202},[33,2325,2326],{"class":39},"\u002F\u002F    Hoist stable values to module scope or use useMemo.\n",[2328,2329,2330],"style",{},"html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .sk71V, html code.shiki .sk71V{--shiki-default:#22863A;--shiki-github-dark:#85E89D}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}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 .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}",{"title":28,"searchDepth":43,"depth":43,"links":2332},[2333,2334,2335,2336,2337,2338,2339,2340,2341,2342],{"id":16,"depth":43,"text":17},{"id":290,"depth":43,"text":291},{"id":690,"depth":43,"text":691},{"id":1008,"depth":43,"text":1009},{"id":1252,"depth":43,"text":1253},{"id":1546,"depth":43,"text":1547},{"id":1798,"depth":43,"text":1799},{"id":1881,"depth":43,"text":1882},{"id":1969,"depth":43,"text":1970},{"id":2246,"depth":43,"text":2247},"JSX compilation to createElement, expression embedding rules, conditional rendering patterns, fragments, spread pitfalls, and the key prop's role in reconciliation. Code-first reference for mid-to-senior React engineers.","md",{},"\u002Freact\u002F02-jsx-deep-dive",{"title":5,"description":2343},"react\u002F02-jsx-deep-dive","DCDAbLbhPDp-I4dPLhoxFcg40v4OWEOjDTI1h-_nxqM",1789924651959]