[{"data":1,"prerenderedAt":2167},["ShallowReactive",2],{"blog-\u002Fblog\u002Freact-prop-drilling-composition-guide":3},{"id":4,"title":5,"body":6,"description":2151,"difficulty":2152,"extension":2153,"framework":2154,"frameworkSlug":2155,"meta":2156,"navigation":351,"order":108,"path":2158,"qaPath":2159,"seo":2160,"stem":2161,"subtopic":2162,"topic":2163,"topicSlug":2164,"updated":2165,"__hash__":2166},"blog\u002Fblog\u002Freact-prop-drilling-composition-guide.md","Prop Drilling and Composition in React — A Complete Guide",{"type":7,"value":8,"toc":2138},"minimark",[9,14,22,191,205,245,248,252,264,493,496,504,510,756,763,767,774,985,990,994,997,1009,1012,1168,1175,1179,1186,1357,1364,1368,1389,1775,1780,1784,1862,1865,1869,1876,2091,2095,2134],[10,11,13],"h2",{"id":12},"what-prop-drilling-is-and-why-it-hurts","What prop drilling is and why it hurts",[15,16,17,21],"p",{},[18,19,20],"strong",{},"Prop drilling"," means passing data through multiple intermediate components\nthat don't use it themselves — they just forward it so a deeply nested child\ncan access it.",[23,24,29],"pre",{"className":25,"code":26,"language":27,"meta":28,"style":28},"language-jsx shiki shiki-themes github-light github-dark","\u002F\u002F `user` is needed only by Button, but it travels through every layer\nfunction App()             { return \u003CPage user={user} \u002F> }\nfunction Page({ user })    { return \u003CSection user={user} \u002F> }\nfunction Section({ user }) { return \u003CWidget user={user} \u002F> }\nfunction Widget({ user })  { return \u003CButton user={user} \u002F> }\nfunction Button({ user })  { return \u003Cspan>{user.name}\u003C\u002Fspan> }\n","jsx","",[30,31,32,41,75,106,134,162],"code",{"__ignoreMap":28},[33,34,37],"span",{"class":35,"line":36},"line",1,[33,38,40],{"class":39},"sJ8bj","\u002F\u002F `user` is needed only by Button, but it travels through every layer\n",[33,42,44,48,52,56,59,62,66,69,72],{"class":35,"line":43},2,[33,45,47],{"class":46},"szBVR","function",[33,49,51],{"class":50},"sScJk"," App",[33,53,55],{"class":54},"sVt8B","()             { ",[33,57,58],{"class":46},"return",[33,60,61],{"class":54}," \u003C",[33,63,65],{"class":64},"sj4cs","Page",[33,67,68],{"class":50}," user",[33,70,71],{"class":46},"=",[33,73,74],{"class":54},"{user} \u002F> }\n",[33,76,78,80,83,86,90,93,95,97,100,102,104],{"class":35,"line":77},3,[33,79,47],{"class":46},[33,81,82],{"class":50}," Page",[33,84,85],{"class":54},"({ ",[33,87,89],{"class":88},"s4XuR","user",[33,91,92],{"class":54}," })    { ",[33,94,58],{"class":46},[33,96,61],{"class":54},[33,98,99],{"class":64},"Section",[33,101,68],{"class":50},[33,103,71],{"class":46},[33,105,74],{"class":54},[33,107,109,111,114,116,118,121,123,125,128,130,132],{"class":35,"line":108},4,[33,110,47],{"class":46},[33,112,113],{"class":50}," Section",[33,115,85],{"class":54},[33,117,89],{"class":88},[33,119,120],{"class":54}," }) { ",[33,122,58],{"class":46},[33,124,61],{"class":54},[33,126,127],{"class":64},"Widget",[33,129,68],{"class":50},[33,131,71],{"class":46},[33,133,74],{"class":54},[33,135,137,139,142,144,146,149,151,153,156,158,160],{"class":35,"line":136},5,[33,138,47],{"class":46},[33,140,141],{"class":50}," Widget",[33,143,85],{"class":54},[33,145,89],{"class":88},[33,147,148],{"class":54}," })  { ",[33,150,58],{"class":46},[33,152,61],{"class":54},[33,154,155],{"class":64},"Button",[33,157,68],{"class":50},[33,159,71],{"class":46},[33,161,74],{"class":54},[33,163,165,167,170,172,174,176,178,180,183,186,188],{"class":35,"line":164},6,[33,166,47],{"class":46},[33,168,169],{"class":50}," Button",[33,171,85],{"class":54},[33,173,89],{"class":88},[33,175,148],{"class":54},[33,177,58],{"class":46},[33,179,61],{"class":54},[33,181,33],{"class":182},"s9eBZ",[33,184,185],{"class":54},">{user.name}\u003C\u002F",[33,187,33],{"class":182},[33,189,190],{"class":54},"> }\n",[15,192,193,195,196,198,199,201,202,204],{},[30,194,65],{},", ",[30,197,99],{},", and ",[30,200,127],{}," all carry a ",[30,203,89],{}," prop they never read.\nThis creates several problems:",[206,207,208,218,224,230],"ol",{},[209,210,211,214,215,217],"li",{},[18,212,213],{},"Coupling"," — every intermediate layer must be updated if the shape of\n",[30,216,89],{}," changes.",[209,219,220,223],{},[18,221,222],{},"Refactor friction"," — adding or renaming a prop means touching every\nlayer in the chain.",[209,225,226,229],{},[18,227,228],{},"Bloated signatures"," — intermediate components accumulate pass-through\nprops that obscure their real interface.",[209,231,232,235,236,238,239,241,242,244],{},[18,233,234],{},"Testing burden"," — tests for ",[30,237,65],{}," and ",[30,240,99],{}," must supply ",[30,243,89],{},"\neven though those tests don't care about it.",[15,246,247],{},"The good news: prop drilling has multiple solutions, ordered from simplest\nto most powerful.",[10,249,251],{"id":250},"solution-1-co-locate-state-closer-to-the-consumer","Solution 1: Co-locate state closer to the consumer",[15,253,254,255,259,260,263],{},"Before reaching for any pattern, ask: ",[256,257,258],"em",{},"does this state really need to live\nso high up?"," Moving state ",[18,261,262],{},"down"," to the component that needs it eliminates\nthe intermediate passes entirely.",[23,265,267],{"className":25,"code":266,"language":27,"meta":28,"style":28},"\u002F\u002F ❌ Modal state in App drills through three layers\nfunction App() {\n  const [isOpen, setIsOpen] = useState(false)\n  return \u003CHeader isOpen={isOpen} onToggle={setIsOpen} \u002F>\n}\n\n\u002F\u002F ✅ Modal state lives right next to the button that opens it\nfunction Header() {\n  const [isOpen, setIsOpen] = useState(false)\n  return (\n    \u003C>\n      \u003Cbutton onClick={() => setIsOpen(true)}>Menu\u003C\u002Fbutton>\n      {isOpen && \u003CMobileMenu onClose={() => setIsOpen(false)} \u002F>}\n    \u003C\u002F>\n  )\n}\n",[30,268,269,274,283,316,342,347,353,359,369,394,402,408,444,476,482,488],{"__ignoreMap":28},[33,270,271],{"class":35,"line":36},[33,272,273],{"class":39},"\u002F\u002F ❌ Modal state in App drills through three layers\n",[33,275,276,278,280],{"class":35,"line":43},[33,277,47],{"class":46},[33,279,51],{"class":50},[33,281,282],{"class":54},"() {\n",[33,284,285,288,291,294,296,299,302,304,307,310,313],{"class":35,"line":77},[33,286,287],{"class":46},"  const",[33,289,290],{"class":54}," [",[33,292,293],{"class":64},"isOpen",[33,295,195],{"class":54},[33,297,298],{"class":64},"setIsOpen",[33,300,301],{"class":54},"] ",[33,303,71],{"class":46},[33,305,306],{"class":50}," useState",[33,308,309],{"class":54},"(",[33,311,312],{"class":64},"false",[33,314,315],{"class":54},")\n",[33,317,318,321,323,326,329,331,334,337,339],{"class":35,"line":108},[33,319,320],{"class":46},"  return",[33,322,61],{"class":54},[33,324,325],{"class":64},"Header",[33,327,328],{"class":50}," isOpen",[33,330,71],{"class":46},[33,332,333],{"class":54},"{isOpen} ",[33,335,336],{"class":50},"onToggle",[33,338,71],{"class":46},[33,340,341],{"class":54},"{setIsOpen} \u002F>\n",[33,343,344],{"class":35,"line":136},[33,345,346],{"class":54},"}\n",[33,348,349],{"class":35,"line":164},[33,350,352],{"emptyLinePlaceholder":351},true,"\n",[33,354,356],{"class":35,"line":355},7,[33,357,358],{"class":39},"\u002F\u002F ✅ Modal state lives right next to the button that opens it\n",[33,360,362,364,367],{"class":35,"line":361},8,[33,363,47],{"class":46},[33,365,366],{"class":50}," Header",[33,368,282],{"class":54},[33,370,372,374,376,378,380,382,384,386,388,390,392],{"class":35,"line":371},9,[33,373,287],{"class":46},[33,375,290],{"class":54},[33,377,293],{"class":64},[33,379,195],{"class":54},[33,381,298],{"class":64},[33,383,301],{"class":54},[33,385,71],{"class":46},[33,387,306],{"class":50},[33,389,309],{"class":54},[33,391,312],{"class":64},[33,393,315],{"class":54},[33,395,397,399],{"class":35,"line":396},10,[33,398,320],{"class":46},[33,400,401],{"class":54}," (\n",[33,403,405],{"class":35,"line":404},11,[33,406,407],{"class":54},"    \u003C>\n",[33,409,411,414,417,420,422,425,428,431,433,436,439,441],{"class":35,"line":410},12,[33,412,413],{"class":54},"      \u003C",[33,415,416],{"class":182},"button",[33,418,419],{"class":50}," onClick",[33,421,71],{"class":46},[33,423,424],{"class":54},"{() ",[33,426,427],{"class":46},"=>",[33,429,430],{"class":50}," setIsOpen",[33,432,309],{"class":54},[33,434,435],{"class":64},"true",[33,437,438],{"class":54},")}>Menu\u003C\u002F",[33,440,416],{"class":182},[33,442,443],{"class":54},">\n",[33,445,447,450,453,455,458,461,463,465,467,469,471,473],{"class":35,"line":446},13,[33,448,449],{"class":54},"      {isOpen ",[33,451,452],{"class":46},"&&",[33,454,61],{"class":54},[33,456,457],{"class":64},"MobileMenu",[33,459,460],{"class":50}," onClose",[33,462,71],{"class":46},[33,464,424],{"class":54},[33,466,427],{"class":46},[33,468,430],{"class":50},[33,470,309],{"class":54},[33,472,312],{"class":64},[33,474,475],{"class":54},")} \u002F>}\n",[33,477,479],{"class":35,"line":478},14,[33,480,481],{"class":54},"    \u003C\u002F>\n",[33,483,485],{"class":35,"line":484},15,[33,486,487],{"class":54},"  )\n",[33,489,491],{"class":35,"line":490},16,[33,492,346],{"class":54},[15,494,495],{},"This is the inverse of \"lift state up\" — only lift when siblings need to\nshare state; keep it local otherwise.",[10,497,499,500,503],{"id":498},"solution-2-component-composition-with-the-children-prop","Solution 2: Component composition with the ",[30,501,502],{},"children"," prop",[15,505,506,507,509],{},"React's ",[30,508,502],{}," prop lets you pass pre-built JSX into a component. The\nparent builds the element with full access to its own data; the intermediary\njust renders it.",[23,511,513],{"className":25,"code":512,"language":27,"meta":28,"style":28},"\u002F\u002F The classic drilling problem:\n\u002F\u002F App has `user`, Button needs `user`, Layout\u002FSection don't care\n\n\u002F\u002F ❌ Drilling\nfunction App()   { return \u003CLayout user={user} \u002F> }\nfunction Layout({ user }) { return \u003CSection user={user} \u002F> }\nfunction Section({ user }) { return \u003CButton user={user} \u002F> }\n\n\u002F\u002F ✅ Composition — App builds Button directly\nfunction App() {\n  return (\n    \u003CLayout>\n      \u003CSection>\n        \u003CButton user={user} \u002F>   {\u002F* App owns the user reference *\u002F}\n      \u003C\u002FSection>\n    \u003C\u002FLayout>\n  )\n}\n\nfunction Layout({ children })  { return \u003Cmain>{children}\u003C\u002Fmain> }\nfunction Section({ children }) { return \u003Cdiv>{children}\u003C\u002Fdiv> }\n\u002F\u002F Neither component knows about user\n",[30,514,515,520,525,529,534,556,581,605,609,614,622,628,637,645,664,673,682,687,692,697,724,750],{"__ignoreMap":28},[33,516,517],{"class":35,"line":36},[33,518,519],{"class":39},"\u002F\u002F The classic drilling problem:\n",[33,521,522],{"class":35,"line":43},[33,523,524],{"class":39},"\u002F\u002F App has `user`, Button needs `user`, Layout\u002FSection don't care\n",[33,526,527],{"class":35,"line":77},[33,528,352],{"emptyLinePlaceholder":351},[33,530,531],{"class":35,"line":108},[33,532,533],{"class":39},"\u002F\u002F ❌ Drilling\n",[33,535,536,538,540,543,545,547,550,552,554],{"class":35,"line":136},[33,537,47],{"class":46},[33,539,51],{"class":50},[33,541,542],{"class":54},"()   { ",[33,544,58],{"class":46},[33,546,61],{"class":54},[33,548,549],{"class":64},"Layout",[33,551,68],{"class":50},[33,553,71],{"class":46},[33,555,74],{"class":54},[33,557,558,560,563,565,567,569,571,573,575,577,579],{"class":35,"line":164},[33,559,47],{"class":46},[33,561,562],{"class":50}," Layout",[33,564,85],{"class":54},[33,566,89],{"class":88},[33,568,120],{"class":54},[33,570,58],{"class":46},[33,572,61],{"class":54},[33,574,99],{"class":64},[33,576,68],{"class":50},[33,578,71],{"class":46},[33,580,74],{"class":54},[33,582,583,585,587,589,591,593,595,597,599,601,603],{"class":35,"line":355},[33,584,47],{"class":46},[33,586,113],{"class":50},[33,588,85],{"class":54},[33,590,89],{"class":88},[33,592,120],{"class":54},[33,594,58],{"class":46},[33,596,61],{"class":54},[33,598,155],{"class":64},[33,600,68],{"class":50},[33,602,71],{"class":46},[33,604,74],{"class":54},[33,606,607],{"class":35,"line":361},[33,608,352],{"emptyLinePlaceholder":351},[33,610,611],{"class":35,"line":371},[33,612,613],{"class":39},"\u002F\u002F ✅ Composition — App builds Button directly\n",[33,615,616,618,620],{"class":35,"line":396},[33,617,47],{"class":46},[33,619,51],{"class":50},[33,621,282],{"class":54},[33,623,624,626],{"class":35,"line":404},[33,625,320],{"class":46},[33,627,401],{"class":54},[33,629,630,633,635],{"class":35,"line":410},[33,631,632],{"class":54},"    \u003C",[33,634,549],{"class":64},[33,636,443],{"class":54},[33,638,639,641,643],{"class":35,"line":446},[33,640,413],{"class":54},[33,642,99],{"class":64},[33,644,443],{"class":54},[33,646,647,650,652,654,656,659,662],{"class":35,"line":478},[33,648,649],{"class":54},"        \u003C",[33,651,155],{"class":64},[33,653,68],{"class":50},[33,655,71],{"class":46},[33,657,658],{"class":54},"{user} \u002F>   {",[33,660,661],{"class":39},"\u002F* App owns the user reference *\u002F",[33,663,346],{"class":54},[33,665,666,669,671],{"class":35,"line":484},[33,667,668],{"class":54},"      \u003C\u002F",[33,670,99],{"class":64},[33,672,443],{"class":54},[33,674,675,678,680],{"class":35,"line":490},[33,676,677],{"class":54},"    \u003C\u002F",[33,679,549],{"class":64},[33,681,443],{"class":54},[33,683,685],{"class":35,"line":684},17,[33,686,487],{"class":54},[33,688,690],{"class":35,"line":689},18,[33,691,346],{"class":54},[33,693,695],{"class":35,"line":694},19,[33,696,352],{"emptyLinePlaceholder":351},[33,698,700,702,704,706,708,710,712,714,717,720,722],{"class":35,"line":699},20,[33,701,47],{"class":46},[33,703,562],{"class":50},[33,705,85],{"class":54},[33,707,502],{"class":88},[33,709,148],{"class":54},[33,711,58],{"class":46},[33,713,61],{"class":54},[33,715,716],{"class":182},"main",[33,718,719],{"class":54},">{children}\u003C\u002F",[33,721,716],{"class":182},[33,723,190],{"class":54},[33,725,727,729,731,733,735,737,739,741,744,746,748],{"class":35,"line":726},21,[33,728,47],{"class":46},[33,730,113],{"class":50},[33,732,85],{"class":54},[33,734,502],{"class":88},[33,736,120],{"class":54},[33,738,58],{"class":46},[33,740,61],{"class":54},[33,742,743],{"class":182},"div",[33,745,719],{"class":54},[33,747,743],{"class":182},[33,749,190],{"class":54},[33,751,753],{"class":35,"line":752},22,[33,754,755],{"class":39},"\u002F\u002F Neither component knows about user\n",[15,757,758,759,762],{},"React calls this ",[18,760,761],{},"inversion of control",": the top-level owner decides what\ngets rendered, and the structural components just provide layout.",[10,764,766],{"id":765},"solution-3-named-slots-for-multiple-content-areas","Solution 3: Named slots for multiple content areas",[15,768,769,770,773],{},"When a component has distinct content regions (header, sidebar, body), use\n",[18,771,772],{},"named props"," — each receiving a JSX element — instead of threading data\nthrough to sub-components.",[23,775,777],{"className":25,"code":776,"language":27,"meta":28,"style":28},"function Layout({ header, sidebar, children }) {\n  return (\n    \u003Cdiv className=\"layout\">\n      \u003Cheader className=\"top-bar\">{header}\u003C\u002Fheader>\n      \u003Caside className=\"side-bar\">{sidebar}\u003C\u002Faside>\n      \u003Cmain className=\"content\">{children}\u003C\u002Fmain>\n    \u003C\u002Fdiv>\n  )\n}\n\n\u002F\u002F The caller builds each slot with its own data — Layout knows nothing\n\u003CLayout\n  header={\u003CNavBar user={user} \u002F>}\n  sidebar={\u003CUserMenu user={user} \u002F>}\n>\n  \u003CFeed posts={posts} \u002F>\n\u003C\u002FLayout>\n",[30,778,779,802,808,825,845,866,885,893,897,901,905,910,918,938,956,960,976],{"__ignoreMap":28},[33,780,781,783,785,787,790,792,795,797,799],{"class":35,"line":36},[33,782,47],{"class":46},[33,784,562],{"class":50},[33,786,85],{"class":54},[33,788,789],{"class":88},"header",[33,791,195],{"class":54},[33,793,794],{"class":88},"sidebar",[33,796,195],{"class":54},[33,798,502],{"class":88},[33,800,801],{"class":54}," }) {\n",[33,803,804,806],{"class":35,"line":43},[33,805,320],{"class":46},[33,807,401],{"class":54},[33,809,810,812,814,817,819,823],{"class":35,"line":77},[33,811,632],{"class":54},[33,813,743],{"class":182},[33,815,816],{"class":50}," className",[33,818,71],{"class":46},[33,820,822],{"class":821},"sZZnC","\"layout\"",[33,824,443],{"class":54},[33,826,827,829,831,833,835,838,841,843],{"class":35,"line":108},[33,828,413],{"class":54},[33,830,789],{"class":182},[33,832,816],{"class":50},[33,834,71],{"class":46},[33,836,837],{"class":821},"\"top-bar\"",[33,839,840],{"class":54},">{header}\u003C\u002F",[33,842,789],{"class":182},[33,844,443],{"class":54},[33,846,847,849,852,854,856,859,862,864],{"class":35,"line":136},[33,848,413],{"class":54},[33,850,851],{"class":182},"aside",[33,853,816],{"class":50},[33,855,71],{"class":46},[33,857,858],{"class":821},"\"side-bar\"",[33,860,861],{"class":54},">{sidebar}\u003C\u002F",[33,863,851],{"class":182},[33,865,443],{"class":54},[33,867,868,870,872,874,876,879,881,883],{"class":35,"line":164},[33,869,413],{"class":54},[33,871,716],{"class":182},[33,873,816],{"class":50},[33,875,71],{"class":46},[33,877,878],{"class":821},"\"content\"",[33,880,719],{"class":54},[33,882,716],{"class":182},[33,884,443],{"class":54},[33,886,887,889,891],{"class":35,"line":355},[33,888,677],{"class":54},[33,890,743],{"class":182},[33,892,443],{"class":54},[33,894,895],{"class":35,"line":361},[33,896,487],{"class":54},[33,898,899],{"class":35,"line":371},[33,900,346],{"class":54},[33,902,903],{"class":35,"line":396},[33,904,352],{"emptyLinePlaceholder":351},[33,906,907],{"class":35,"line":404},[33,908,909],{"class":39},"\u002F\u002F The caller builds each slot with its own data — Layout knows nothing\n",[33,911,912,915],{"class":35,"line":410},[33,913,914],{"class":54},"\u003C",[33,916,917],{"class":64},"Layout\n",[33,919,920,923,925,928,931,933,935],{"class":35,"line":446},[33,921,922],{"class":50},"  header",[33,924,71],{"class":46},[33,926,927],{"class":54},"{\u003C",[33,929,930],{"class":64},"NavBar",[33,932,68],{"class":50},[33,934,71],{"class":46},[33,936,937],{"class":54},"{user} \u002F>}\n",[33,939,940,943,945,947,950,952,954],{"class":35,"line":478},[33,941,942],{"class":50},"  sidebar",[33,944,71],{"class":46},[33,946,927],{"class":54},[33,948,949],{"class":64},"UserMenu",[33,951,68],{"class":50},[33,953,71],{"class":46},[33,955,937],{"class":54},[33,957,958],{"class":35,"line":484},[33,959,443],{"class":54},[33,961,962,965,968,971,973],{"class":35,"line":490},[33,963,964],{"class":54},"  \u003C",[33,966,967],{"class":64},"Feed",[33,969,970],{"class":50}," posts",[33,972,71],{"class":46},[33,974,975],{"class":54},"{posts} \u002F>\n",[33,977,978,981,983],{"class":35,"line":684},[33,979,980],{"class":54},"\u003C\u002F",[33,982,549],{"class":64},[33,984,443],{"class":54},[15,986,987,989],{},[30,988,549],{}," is a pure structural component. It gets no data props at all. The\ncaller controls all content by composing JSX into the slots.",[10,991,993],{"id":992},"solution-4-context-api-for-cross-cutting-concerns","Solution 4: Context API for cross-cutting concerns",[15,995,996],{},"Composition works well when you control the tree from the top. It gets\nawkward when:",[998,999,1000,1003,1006],"ul",{},[209,1001,1002],{},"The consumer is many levels deep inside a third-party library",[209,1004,1005],{},"The data is needed by many unrelated subtrees (authentication, theme, locale)",[209,1007,1008],{},"Composing JSX from the top would make the call site unreadable",[15,1010,1011],{},"In those cases, Context is the right tool:",[23,1013,1015],{"className":25,"code":1014,"language":27,"meta":28,"style":28},"const UserContext = createContext(null)\n\nfunction App() {\n  return (\n    \u003CUserContext.Provider value={user}>\n      {\u002F* No user prop anywhere — consumers read it directly *\u002F}\n      \u003CHeader \u002F>\n      \u003CMain \u002F>\n      \u003CFooter \u002F>\n    \u003C\u002FUserContext.Provider>\n  )\n}\n\nfunction Button() {\n  const user = useContext(UserContext)\n  return \u003Cspan>{user.name}\u003C\u002Fspan>\n}\n",[30,1016,1017,1038,1042,1050,1056,1071,1081,1090,1099,1108,1116,1120,1124,1128,1136,1150,1164],{"__ignoreMap":28},[33,1018,1019,1022,1025,1028,1031,1033,1036],{"class":35,"line":36},[33,1020,1021],{"class":46},"const",[33,1023,1024],{"class":64}," UserContext",[33,1026,1027],{"class":46}," =",[33,1029,1030],{"class":50}," createContext",[33,1032,309],{"class":54},[33,1034,1035],{"class":64},"null",[33,1037,315],{"class":54},[33,1039,1040],{"class":35,"line":43},[33,1041,352],{"emptyLinePlaceholder":351},[33,1043,1044,1046,1048],{"class":35,"line":77},[33,1045,47],{"class":46},[33,1047,51],{"class":50},[33,1049,282],{"class":54},[33,1051,1052,1054],{"class":35,"line":108},[33,1053,320],{"class":46},[33,1055,401],{"class":54},[33,1057,1058,1060,1063,1066,1068],{"class":35,"line":136},[33,1059,632],{"class":54},[33,1061,1062],{"class":64},"UserContext.Provider",[33,1064,1065],{"class":50}," value",[33,1067,71],{"class":46},[33,1069,1070],{"class":54},"{user}>\n",[33,1072,1073,1076,1079],{"class":35,"line":164},[33,1074,1075],{"class":54},"      {",[33,1077,1078],{"class":39},"\u002F* No user prop anywhere — consumers read it directly *\u002F",[33,1080,346],{"class":54},[33,1082,1083,1085,1087],{"class":35,"line":355},[33,1084,413],{"class":54},[33,1086,325],{"class":64},[33,1088,1089],{"class":54}," \u002F>\n",[33,1091,1092,1094,1097],{"class":35,"line":361},[33,1093,413],{"class":54},[33,1095,1096],{"class":64},"Main",[33,1098,1089],{"class":54},[33,1100,1101,1103,1106],{"class":35,"line":371},[33,1102,413],{"class":54},[33,1104,1105],{"class":64},"Footer",[33,1107,1089],{"class":54},[33,1109,1110,1112,1114],{"class":35,"line":396},[33,1111,677],{"class":54},[33,1113,1062],{"class":64},[33,1115,443],{"class":54},[33,1117,1118],{"class":35,"line":404},[33,1119,487],{"class":54},[33,1121,1122],{"class":35,"line":410},[33,1123,346],{"class":54},[33,1125,1126],{"class":35,"line":446},[33,1127,352],{"emptyLinePlaceholder":351},[33,1129,1130,1132,1134],{"class":35,"line":478},[33,1131,47],{"class":46},[33,1133,169],{"class":50},[33,1135,282],{"class":54},[33,1137,1138,1140,1142,1144,1147],{"class":35,"line":484},[33,1139,287],{"class":46},[33,1141,68],{"class":64},[33,1143,1027],{"class":46},[33,1145,1146],{"class":50}," useContext",[33,1148,1149],{"class":54},"(UserContext)\n",[33,1151,1152,1154,1156,1158,1160,1162],{"class":35,"line":490},[33,1153,320],{"class":46},[33,1155,61],{"class":54},[33,1157,33],{"class":182},[33,1159,185],{"class":54},[33,1161,33],{"class":182},[33,1163,443],{"class":54},[33,1165,1166],{"class":35,"line":684},[33,1167,346],{"class":54},[15,1169,1170,1171,1174],{},"Context is best for ",[18,1172,1173],{},"infrequently changing"," global values. For data that\nchanges often (like a live count), all consumers re-render on every change —\nwhich can be expensive.",[10,1176,1178],{"id":1177},"solution-5-render-props-for-injectable-logic","Solution 5: Render props for injectable logic",[15,1180,1181,1182,1185],{},"A ",[18,1183,1184],{},"render prop"," is a prop whose value is a function that returns JSX. The\ncomponent calls the function, passing internal state to the caller:",[23,1187,1189],{"className":25,"code":1188,"language":27,"meta":28,"style":28},"function MouseTracker({ render }) {\n  const [pos, setPos] = useState({ x: 0, y: 0 })\n\n  return (\n    \u003Cdiv onMouseMove={e => setPos({ x: e.clientX, y: e.clientY })}>\n      {render(pos)}\n    \u003C\u002Fdiv>\n  )\n}\n\n\u002F\u002F The consumer decides what to render with the tracked position\n\u003CMouseTracker render={({ x, y }) => \u003CCrosshair x={x} y={y} \u002F>} \u002F>\n",[30,1190,1191,1205,1239,1243,1249,1275,1284,1292,1296,1300,1304,1309],{"__ignoreMap":28},[33,1192,1193,1195,1198,1200,1203],{"class":35,"line":36},[33,1194,47],{"class":46},[33,1196,1197],{"class":50}," MouseTracker",[33,1199,85],{"class":54},[33,1201,1202],{"class":88},"render",[33,1204,801],{"class":54},[33,1206,1207,1209,1211,1214,1216,1219,1221,1223,1225,1228,1231,1234,1236],{"class":35,"line":43},[33,1208,287],{"class":46},[33,1210,290],{"class":54},[33,1212,1213],{"class":64},"pos",[33,1215,195],{"class":54},[33,1217,1218],{"class":64},"setPos",[33,1220,301],{"class":54},[33,1222,71],{"class":46},[33,1224,306],{"class":50},[33,1226,1227],{"class":54},"({ x: ",[33,1229,1230],{"class":64},"0",[33,1232,1233],{"class":54},", y: ",[33,1235,1230],{"class":64},[33,1237,1238],{"class":54}," })\n",[33,1240,1241],{"class":35,"line":77},[33,1242,352],{"emptyLinePlaceholder":351},[33,1244,1245,1247],{"class":35,"line":108},[33,1246,320],{"class":46},[33,1248,401],{"class":54},[33,1250,1251,1253,1255,1258,1260,1263,1266,1269,1272],{"class":35,"line":136},[33,1252,632],{"class":54},[33,1254,743],{"class":182},[33,1256,1257],{"class":50}," onMouseMove",[33,1259,71],{"class":46},[33,1261,1262],{"class":54},"{",[33,1264,1265],{"class":88},"e",[33,1267,1268],{"class":46}," =>",[33,1270,1271],{"class":50}," setPos",[33,1273,1274],{"class":54},"({ x: e.clientX, y: e.clientY })}>\n",[33,1276,1277,1279,1281],{"class":35,"line":164},[33,1278,1075],{"class":54},[33,1280,1202],{"class":50},[33,1282,1283],{"class":54},"(pos)}\n",[33,1285,1286,1288,1290],{"class":35,"line":355},[33,1287,677],{"class":54},[33,1289,743],{"class":182},[33,1291,443],{"class":54},[33,1293,1294],{"class":35,"line":361},[33,1295,487],{"class":54},[33,1297,1298],{"class":35,"line":371},[33,1299,346],{"class":54},[33,1301,1302],{"class":35,"line":396},[33,1303,352],{"emptyLinePlaceholder":351},[33,1305,1306],{"class":35,"line":404},[33,1307,1308],{"class":39},"\u002F\u002F The consumer decides what to render with the tracked position\n",[33,1310,1311,1313,1316,1319,1321,1324,1327,1329,1332,1335,1337,1339,1342,1345,1347,1350,1352,1354],{"class":35,"line":410},[33,1312,914],{"class":54},[33,1314,1315],{"class":64},"MouseTracker",[33,1317,1318],{"class":50}," render",[33,1320,71],{"class":46},[33,1322,1323],{"class":54},"{({ ",[33,1325,1326],{"class":88},"x",[33,1328,195],{"class":54},[33,1330,1331],{"class":88},"y",[33,1333,1334],{"class":54}," }) ",[33,1336,427],{"class":46},[33,1338,61],{"class":54},[33,1340,1341],{"class":64},"Crosshair",[33,1343,1344],{"class":50}," x",[33,1346,71],{"class":46},[33,1348,1349],{"class":54},"{x} ",[33,1351,1331],{"class":50},[33,1353,71],{"class":46},[33,1355,1356],{"class":54},"{y} \u002F>} \u002F>\n",[15,1358,1359,1360,1363],{},"Render props share logic without a prop-drilling chain, but they nest deeply\nin complex cases. ",[18,1361,1362],{},"Custom hooks"," have mostly replaced render props for\nlogic sharing in modern React.",[10,1365,1367],{"id":1366},"solution-6-compound-components-for-component-families","Solution 6: Compound components for component families",[15,1369,1370,1371,1374,1375,238,1378,1381,1382,238,1385,1388],{},"The ",[18,1372,1373],{},"compound component"," pattern combines Context + composition to create a\ngroup of components that work together — like ",[30,1376,1377],{},"\u003CSelect>",[30,1379,1380],{},"\u003COption>",", or\n",[30,1383,1384],{},"\u003CAccordion>",[30,1386,1387],{},"\u003CAccordion.Item>",".",[23,1390,1392],{"className":25,"code":1391,"language":27,"meta":28,"style":28},"const AccordionCtx = createContext(null)\n\nfunction Accordion({ children }) {\n  const [openId, setOpenId] = useState(null)\n  return (\n    \u003CAccordionCtx.Provider value={{ openId, setOpenId }}>\n      \u003Cdiv>{children}\u003C\u002Fdiv>\n    \u003C\u002FAccordionCtx.Provider>\n  )\n}\n\nAccordion.Item = function Item({ id, title, children }) {\n  const { openId, setOpenId } = useContext(AccordionCtx)\n  const isOpen = openId === id\n\n  return (\n    \u003Cdiv>\n      \u003Cbutton onClick={() => setOpenId(isOpen ? null : id)}>{title}\u003C\u002Fbutton>\n      {isOpen && \u003Cdiv>{children}\u003C\u002Fdiv>}\n    \u003C\u002Fdiv>\n  )\n}\n\n\u002F\u002F Usage — no explicit state passing at all\n\u003CAccordion>\n  \u003CAccordion.Item id=\"faq-1\" title=\"What is React?\">\n    A UI library for building component trees.\n  \u003C\u002FAccordion.Item>\n  \u003CAccordion.Item id=\"faq-2\" title=\"What is JSX?\">\n    Syntactic sugar for React.createElement.\n  \u003C\u002FAccordion.Item>\n\u003C\u002FAccordion>\n",[30,1393,1394,1411,1415,1428,1454,1460,1474,1486,1494,1498,1502,1506,1538,1561,1578,1582,1588,1596,1632,1649,1657,1661,1665,1670,1676,1686,1712,1718,1728,1751,1757,1766],{"__ignoreMap":28},[33,1395,1396,1398,1401,1403,1405,1407,1409],{"class":35,"line":36},[33,1397,1021],{"class":46},[33,1399,1400],{"class":64}," AccordionCtx",[33,1402,1027],{"class":46},[33,1404,1030],{"class":50},[33,1406,309],{"class":54},[33,1408,1035],{"class":64},[33,1410,315],{"class":54},[33,1412,1413],{"class":35,"line":43},[33,1414,352],{"emptyLinePlaceholder":351},[33,1416,1417,1419,1422,1424,1426],{"class":35,"line":77},[33,1418,47],{"class":46},[33,1420,1421],{"class":50}," Accordion",[33,1423,85],{"class":54},[33,1425,502],{"class":88},[33,1427,801],{"class":54},[33,1429,1430,1432,1434,1437,1439,1442,1444,1446,1448,1450,1452],{"class":35,"line":108},[33,1431,287],{"class":46},[33,1433,290],{"class":54},[33,1435,1436],{"class":64},"openId",[33,1438,195],{"class":54},[33,1440,1441],{"class":64},"setOpenId",[33,1443,301],{"class":54},[33,1445,71],{"class":46},[33,1447,306],{"class":50},[33,1449,309],{"class":54},[33,1451,1035],{"class":64},[33,1453,315],{"class":54},[33,1455,1456,1458],{"class":35,"line":136},[33,1457,320],{"class":46},[33,1459,401],{"class":54},[33,1461,1462,1464,1467,1469,1471],{"class":35,"line":164},[33,1463,632],{"class":54},[33,1465,1466],{"class":64},"AccordionCtx.Provider",[33,1468,1065],{"class":50},[33,1470,71],{"class":46},[33,1472,1473],{"class":54},"{{ openId, setOpenId }}>\n",[33,1475,1476,1478,1480,1482,1484],{"class":35,"line":355},[33,1477,413],{"class":54},[33,1479,743],{"class":182},[33,1481,719],{"class":54},[33,1483,743],{"class":182},[33,1485,443],{"class":54},[33,1487,1488,1490,1492],{"class":35,"line":361},[33,1489,677],{"class":54},[33,1491,1466],{"class":64},[33,1493,443],{"class":54},[33,1495,1496],{"class":35,"line":371},[33,1497,487],{"class":54},[33,1499,1500],{"class":35,"line":396},[33,1501,346],{"class":54},[33,1503,1504],{"class":35,"line":404},[33,1505,352],{"emptyLinePlaceholder":351},[33,1507,1508,1511,1514,1516,1519,1522,1524,1527,1529,1532,1534,1536],{"class":35,"line":410},[33,1509,1510],{"class":54},"Accordion.",[33,1512,1513],{"class":50},"Item",[33,1515,1027],{"class":46},[33,1517,1518],{"class":46}," function",[33,1520,1521],{"class":50}," Item",[33,1523,85],{"class":54},[33,1525,1526],{"class":88},"id",[33,1528,195],{"class":54},[33,1530,1531],{"class":88},"title",[33,1533,195],{"class":54},[33,1535,502],{"class":88},[33,1537,801],{"class":54},[33,1539,1540,1542,1545,1547,1549,1551,1554,1556,1558],{"class":35,"line":446},[33,1541,287],{"class":46},[33,1543,1544],{"class":54}," { ",[33,1546,1436],{"class":64},[33,1548,195],{"class":54},[33,1550,1441],{"class":64},[33,1552,1553],{"class":54}," } ",[33,1555,71],{"class":46},[33,1557,1146],{"class":50},[33,1559,1560],{"class":54},"(AccordionCtx)\n",[33,1562,1563,1565,1567,1569,1572,1575],{"class":35,"line":478},[33,1564,287],{"class":46},[33,1566,328],{"class":64},[33,1568,1027],{"class":46},[33,1570,1571],{"class":54}," openId ",[33,1573,1574],{"class":46},"===",[33,1576,1577],{"class":54}," id\n",[33,1579,1580],{"class":35,"line":484},[33,1581,352],{"emptyLinePlaceholder":351},[33,1583,1584,1586],{"class":35,"line":490},[33,1585,320],{"class":46},[33,1587,401],{"class":54},[33,1589,1590,1592,1594],{"class":35,"line":684},[33,1591,632],{"class":54},[33,1593,743],{"class":182},[33,1595,443],{"class":54},[33,1597,1598,1600,1602,1604,1606,1608,1610,1613,1616,1619,1622,1625,1628,1630],{"class":35,"line":689},[33,1599,413],{"class":54},[33,1601,416],{"class":182},[33,1603,419],{"class":50},[33,1605,71],{"class":46},[33,1607,424],{"class":54},[33,1609,427],{"class":46},[33,1611,1612],{"class":50}," setOpenId",[33,1614,1615],{"class":54},"(isOpen ",[33,1617,1618],{"class":46},"?",[33,1620,1621],{"class":64}," null",[33,1623,1624],{"class":46}," :",[33,1626,1627],{"class":54}," id)}>{title}\u003C\u002F",[33,1629,416],{"class":182},[33,1631,443],{"class":54},[33,1633,1634,1636,1638,1640,1642,1644,1646],{"class":35,"line":694},[33,1635,449],{"class":54},[33,1637,452],{"class":46},[33,1639,61],{"class":54},[33,1641,743],{"class":182},[33,1643,719],{"class":54},[33,1645,743],{"class":182},[33,1647,1648],{"class":54},">}\n",[33,1650,1651,1653,1655],{"class":35,"line":699},[33,1652,677],{"class":54},[33,1654,743],{"class":182},[33,1656,443],{"class":54},[33,1658,1659],{"class":35,"line":726},[33,1660,487],{"class":54},[33,1662,1663],{"class":35,"line":752},[33,1664,346],{"class":54},[33,1666,1668],{"class":35,"line":1667},23,[33,1669,352],{"emptyLinePlaceholder":351},[33,1671,1673],{"class":35,"line":1672},24,[33,1674,1675],{"class":39},"\u002F\u002F Usage — no explicit state passing at all\n",[33,1677,1679,1681,1684],{"class":35,"line":1678},25,[33,1680,914],{"class":54},[33,1682,1683],{"class":64},"Accordion",[33,1685,443],{"class":54},[33,1687,1689,1691,1694,1697,1699,1702,1705,1707,1710],{"class":35,"line":1688},26,[33,1690,964],{"class":54},[33,1692,1693],{"class":64},"Accordion.Item",[33,1695,1696],{"class":50}," id",[33,1698,71],{"class":46},[33,1700,1701],{"class":821},"\"faq-1\"",[33,1703,1704],{"class":50}," title",[33,1706,71],{"class":46},[33,1708,1709],{"class":821},"\"What is React?\"",[33,1711,443],{"class":54},[33,1713,1715],{"class":35,"line":1714},27,[33,1716,1717],{"class":54},"    A UI library for building component trees.\n",[33,1719,1721,1724,1726],{"class":35,"line":1720},28,[33,1722,1723],{"class":54},"  \u003C\u002F",[33,1725,1693],{"class":64},[33,1727,443],{"class":54},[33,1729,1731,1733,1735,1737,1739,1742,1744,1746,1749],{"class":35,"line":1730},29,[33,1732,964],{"class":54},[33,1734,1693],{"class":64},[33,1736,1696],{"class":50},[33,1738,71],{"class":46},[33,1740,1741],{"class":821},"\"faq-2\"",[33,1743,1704],{"class":50},[33,1745,71],{"class":46},[33,1747,1748],{"class":821},"\"What is JSX?\"",[33,1750,443],{"class":54},[33,1752,1754],{"class":35,"line":1753},30,[33,1755,1756],{"class":54},"    Syntactic sugar for React.createElement.\n",[33,1758,1760,1762,1764],{"class":35,"line":1759},31,[33,1761,1723],{"class":54},[33,1763,1693],{"class":64},[33,1765,443],{"class":54},[33,1767,1769,1771,1773],{"class":35,"line":1768},32,[33,1770,980],{"class":54},[33,1772,1683],{"class":64},[33,1774,443],{"class":54},[15,1776,1777,1778,1388],{},"The caller gets a clean, declarative JSX API. State is shared via the\nimplicit Context created inside ",[30,1779,1683],{},[10,1781,1783],{"id":1782},"choosing-the-right-solution","Choosing the right solution",[1785,1786,1787,1800],"table",{},[1788,1789,1790],"thead",{},[1791,1792,1793,1797],"tr",{},[1794,1795,1796],"th",{},"Situation",[1794,1798,1799],{},"Best approach",[1801,1802,1803,1812,1822,1830,1838,1846,1854],"tbody",{},[1791,1804,1805,1809],{},[1806,1807,1808],"td",{},"State used only in a subtree",[1806,1810,1811],{},"Co-locate — move state down",[1791,1813,1814,1817],{},[1806,1815,1816],{},"Data needed by a deeply nested child you build",[1806,1818,1819,1820],{},"Composition \u002F ",[30,1821,502],{},[1791,1823,1824,1827],{},[1806,1825,1826],{},"Multiple distinct content areas in a layout",[1806,1828,1829],{},"Named slots (props accepting JSX)",[1791,1831,1832,1835],{},[1806,1833,1834],{},"Data needed across many unrelated subtrees",[1806,1836,1837],{},"Context API",[1791,1839,1840,1843],{},[1806,1841,1842],{},"Logic to share without a hierarchy",[1806,1844,1845],{},"Custom hook (or render prop)",[1791,1847,1848,1851],{},[1806,1849,1850],{},"Group of related UI components",[1806,1852,1853],{},"Compound components",[1791,1855,1856,1859],{},[1806,1857,1858],{},"Frequently updating shared state, many consumers",[1806,1860,1861],{},"Zustand \u002F Redux",[15,1863,1864],{},"Start at the top of this list. Only move down when the simpler option doesn't\nfit.",[10,1866,1868],{"id":1867},"typescript-tip-spread-rest-props-to-avoid-prop-drilling-on-wrappers","TypeScript tip: spread rest props to avoid prop drilling on wrappers",[15,1870,1871,1872,1875],{},"When writing a component that wraps a native element, extend its HTML\nattributes and spread ",[30,1873,1874],{},"...rest",". This forwards every native prop without\nlisting each one:",[23,1877,1881],{"className":1878,"code":1879,"language":1880,"meta":28,"style":28},"language-tsx shiki shiki-themes github-light github-dark","import { ButtonHTMLAttributes } from 'react'\n\ninterface IconButtonProps extends ButtonHTMLAttributes\u003CHTMLButtonElement> {\n  icon: string\n}\n\nfunction IconButton({ icon, ...rest }: IconButtonProps) {\n  return (\n    \u003Cbutton {...rest}>\n      \u003Ci className={`icon-${icon}`} \u002F>\n      {rest.children}\n    \u003C\u002Fbutton>\n  )\n}\n\n\u002F\u002F Passes onClick, disabled, aria-label, type, etc. without drilling each\n\u003CIconButton icon=\"save\" onClick={save} disabled={!dirty} aria-label=\"Save\" \u002F>\n","tsx",[30,1882,1883,1897,1901,1923,1934,1938,1942,1972,1978,1992,2016,2021,2029,2033,2037,2041,2046],{"__ignoreMap":28},[33,1884,1885,1888,1891,1894],{"class":35,"line":36},[33,1886,1887],{"class":46},"import",[33,1889,1890],{"class":54}," { ButtonHTMLAttributes } ",[33,1892,1893],{"class":46},"from",[33,1895,1896],{"class":821}," 'react'\n",[33,1898,1899],{"class":35,"line":43},[33,1900,352],{"emptyLinePlaceholder":351},[33,1902,1903,1906,1909,1912,1915,1917,1920],{"class":35,"line":77},[33,1904,1905],{"class":46},"interface",[33,1907,1908],{"class":50}," IconButtonProps",[33,1910,1911],{"class":46}," extends",[33,1913,1914],{"class":50}," ButtonHTMLAttributes",[33,1916,914],{"class":54},[33,1918,1919],{"class":50},"HTMLButtonElement",[33,1921,1922],{"class":54},"> {\n",[33,1924,1925,1928,1931],{"class":35,"line":108},[33,1926,1927],{"class":88},"  icon",[33,1929,1930],{"class":46},":",[33,1932,1933],{"class":64}," string\n",[33,1935,1936],{"class":35,"line":136},[33,1937,346],{"class":54},[33,1939,1940],{"class":35,"line":164},[33,1941,352],{"emptyLinePlaceholder":351},[33,1943,1944,1946,1949,1951,1954,1956,1959,1962,1965,1967,1969],{"class":35,"line":355},[33,1945,47],{"class":46},[33,1947,1948],{"class":50}," IconButton",[33,1950,85],{"class":54},[33,1952,1953],{"class":88},"icon",[33,1955,195],{"class":54},[33,1957,1958],{"class":46},"...",[33,1960,1961],{"class":88},"rest",[33,1963,1964],{"class":54}," }",[33,1966,1930],{"class":46},[33,1968,1908],{"class":50},[33,1970,1971],{"class":54},") {\n",[33,1973,1974,1976],{"class":35,"line":361},[33,1975,320],{"class":46},[33,1977,401],{"class":54},[33,1979,1980,1982,1984,1987,1989],{"class":35,"line":371},[33,1981,632],{"class":54},[33,1983,416],{"class":182},[33,1985,1986],{"class":54}," {",[33,1988,1958],{"class":46},[33,1990,1991],{"class":54},"rest}>\n",[33,1993,1994,1996,1999,2001,2003,2005,2008,2010,2013],{"class":35,"line":396},[33,1995,413],{"class":54},[33,1997,1998],{"class":182},"i",[33,2000,816],{"class":50},[33,2002,71],{"class":46},[33,2004,1262],{"class":54},[33,2006,2007],{"class":821},"`icon-${",[33,2009,1953],{"class":54},[33,2011,2012],{"class":821},"}`",[33,2014,2015],{"class":54},"} \u002F>\n",[33,2017,2018],{"class":35,"line":404},[33,2019,2020],{"class":54},"      {rest.children}\n",[33,2022,2023,2025,2027],{"class":35,"line":410},[33,2024,677],{"class":54},[33,2026,416],{"class":182},[33,2028,443],{"class":54},[33,2030,2031],{"class":35,"line":446},[33,2032,487],{"class":54},[33,2034,2035],{"class":35,"line":478},[33,2036,346],{"class":54},[33,2038,2039],{"class":35,"line":484},[33,2040,352],{"emptyLinePlaceholder":351},[33,2042,2043],{"class":35,"line":490},[33,2044,2045],{"class":39},"\u002F\u002F Passes onClick, disabled, aria-label, type, etc. without drilling each\n",[33,2047,2048,2050,2053,2056,2058,2061,2063,2065,2068,2071,2073,2075,2078,2081,2084,2086,2089],{"class":35,"line":684},[33,2049,914],{"class":54},[33,2051,2052],{"class":64},"IconButton",[33,2054,2055],{"class":50}," icon",[33,2057,71],{"class":46},[33,2059,2060],{"class":821},"\"save\"",[33,2062,419],{"class":50},[33,2064,71],{"class":46},[33,2066,2067],{"class":54},"{save} ",[33,2069,2070],{"class":50},"disabled",[33,2072,71],{"class":46},[33,2074,1262],{"class":54},[33,2076,2077],{"class":46},"!",[33,2079,2080],{"class":54},"dirty} ",[33,2082,2083],{"class":50},"aria-label",[33,2085,71],{"class":46},[33,2087,2088],{"class":821},"\"Save\"",[33,2090,1089],{"class":54},[10,2092,2094],{"id":2093},"key-interview-points","Key interview points",[998,2096,2097,2104,2110,2119,2126,2131],{},[209,2098,2099,2100,2103],{},"Prop drilling is not inherently wrong — passing a prop ",[18,2101,2102],{},"one level"," down\nis fine. The problem starts at two or three layers of pass-through.",[209,2105,1370,2106,2109],{},[18,2107,2108],{},"first"," fix to try is co-location — move state closer to the consumer.",[209,2111,2112,2115,2116,2118],{},[18,2113,2114],{},"Composition"," (",[30,2117,502],{},", named slots) eliminates drilling by letting the\nowner build the element directly.",[209,2120,2121,2122,2125],{},"Context is for ",[18,2123,2124],{},"cross-cutting, infrequently changing"," data — not a\nreplacement for any prop passing.",[209,2127,2128,2130],{},[18,2129,1853],{}," share implicit state between a parent and its child\nsub-components via Context, giving callers a clean JSX API.",[209,2132,2133],{},"Don't jump straight to Redux — work through this list in order.",[2135,2136,2137],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":28,"searchDepth":43,"depth":43,"links":2139},[2140,2141,2142,2144,2145,2146,2147,2148,2149,2150],{"id":12,"depth":43,"text":13},{"id":250,"depth":43,"text":251},{"id":498,"depth":43,"text":2143},"Solution 2: Component composition with the children prop",{"id":765,"depth":43,"text":766},{"id":992,"depth":43,"text":993},{"id":1177,"depth":43,"text":1178},{"id":1366,"depth":43,"text":1367},{"id":1782,"depth":43,"text":1783},{"id":1867,"depth":43,"text":1868},{"id":2093,"depth":43,"text":2094},"A complete guide to prop drilling and composition in React — what prop drilling is, why it hurts, and how to fix it with children, slots, Context, render props, and compound components.","medium","md","React","react",{"subtopicSlug":2157},"prop-drilling-composition","\u002Fblog\u002Freact-prop-drilling-composition-guide","\u002Freact\u002Fstate-and-data-flow\u002Fprop-drilling-composition",{"title":5,"description":2151},"blog\u002Freact-prop-drilling-composition-guide","Prop Drilling and Composition","State and Data Flow","state-and-data-flow","2026-06-24","P3CduujEhkS-gKaLnJf_jLHOr51tMO4vcdL8hizZpzo",1782244083299]