[{"data":1,"prerenderedAt":1908},["ShallowReactive",2],{"blog-\u002Fblog\u002Freact-props-component-types-guide":3},{"id":4,"title":5,"body":6,"description":1892,"difficulty":1893,"extension":1894,"framework":1895,"frameworkSlug":1896,"meta":1897,"navigation":88,"order":48,"path":1899,"qaPath":1900,"seo":1901,"stem":1902,"subtopic":1903,"topic":1904,"topicSlug":1905,"updated":1906,"__hash__":1907},"blog\u002Fblog\u002Freact-props-component-types-guide.md","React Props and Component Types — A Complete Interview Guide",{"type":7,"value":8,"toc":1879},"minimark",[9,14,27,212,219,223,226,461,464,575,596,600,607,763,779,792,796,799,900,907,911,920,1062,1065,1069,1120,1131,1259,1263,1266,1356,1359,1405,1408,1412,1415,1580,1583,1587,1590,1696,1699,1720,1726,1730,1733,1840,1854,1861,1865,1872,1875],[10,11,13],"h2",{"id":12},"the-mental-model-for-props","The mental model for props",[15,16,17,18,22,23,26],"p",{},"Props are the mechanism React uses to pass data ",[19,20,21],"strong",{},"down"," through the component\ntree. They are received as a plain JavaScript object and are ",[19,24,25],{},"read-only"," —\na component must never mutate its own props.",[28,29,34],"pre",{"className":30,"code":31,"language":32,"meta":33,"style":33},"language-jsx shiki shiki-themes github-light github-dark","\u002F\u002F Parent passes data down\n\u003CUserCard name=\"Alice\" role=\"admin\" isActive \u002F>\n\n\u002F\u002F Child receives a frozen snapshot\nfunction UserCard({ name, role, isActive }) {\n  return (\n    \u003Cdiv className={`card ${isActive ? 'active' : ''}`}>\n      \u003Cstrong>{name}\u003C\u002Fstrong> — {role}\n    \u003C\u002Fdiv>\n  )\n}\n","jsx","",[35,36,37,46,83,90,96,126,135,173,189,200,206],"code",{"__ignoreMap":33},[38,39,42],"span",{"class":40,"line":41},"line",1,[38,43,45],{"class":44},"sJ8bj","\u002F\u002F Parent passes data down\n",[38,47,49,53,57,61,65,69,72,74,77,80],{"class":40,"line":48},2,[38,50,52],{"class":51},"sVt8B","\u003C",[38,54,56],{"class":55},"sj4cs","UserCard",[38,58,60],{"class":59},"sScJk"," name",[38,62,64],{"class":63},"szBVR","=",[38,66,68],{"class":67},"sZZnC","\"Alice\"",[38,70,71],{"class":59}," role",[38,73,64],{"class":63},[38,75,76],{"class":67},"\"admin\"",[38,78,79],{"class":59}," isActive",[38,81,82],{"class":51}," \u002F>\n",[38,84,86],{"class":40,"line":85},3,[38,87,89],{"emptyLinePlaceholder":88},true,"\n",[38,91,93],{"class":40,"line":92},4,[38,94,95],{"class":44},"\u002F\u002F Child receives a frozen snapshot\n",[38,97,99,102,105,108,112,115,118,120,123],{"class":40,"line":98},5,[38,100,101],{"class":63},"function",[38,103,104],{"class":59}," UserCard",[38,106,107],{"class":51},"({ ",[38,109,111],{"class":110},"s4XuR","name",[38,113,114],{"class":51},", ",[38,116,117],{"class":110},"role",[38,119,114],{"class":51},[38,121,122],{"class":110},"isActive",[38,124,125],{"class":51}," }) {\n",[38,127,129,132],{"class":40,"line":128},6,[38,130,131],{"class":63},"  return",[38,133,134],{"class":51}," (\n",[38,136,138,141,145,148,150,153,156,158,161,164,167,170],{"class":40,"line":137},7,[38,139,140],{"class":51},"    \u003C",[38,142,144],{"class":143},"s9eBZ","div",[38,146,147],{"class":59}," className",[38,149,64],{"class":63},[38,151,152],{"class":51},"{",[38,154,155],{"class":67},"`card ${",[38,157,122],{"class":51},[38,159,160],{"class":63}," ?",[38,162,163],{"class":67}," 'active'",[38,165,166],{"class":63}," :",[38,168,169],{"class":67}," ''}`",[38,171,172],{"class":51},"}>\n",[38,174,176,179,181,184,186],{"class":40,"line":175},8,[38,177,178],{"class":51},"      \u003C",[38,180,19],{"class":143},[38,182,183],{"class":51},">{name}\u003C\u002F",[38,185,19],{"class":143},[38,187,188],{"class":51},"> — {role}\n",[38,190,192,195,197],{"class":40,"line":191},9,[38,193,194],{"class":51},"    \u003C\u002F",[38,196,144],{"class":143},[38,198,199],{"class":51},">\n",[38,201,203],{"class":40,"line":202},10,[38,204,205],{"class":51},"  )\n",[38,207,209],{"class":40,"line":208},11,[38,210,211],{"class":51},"}\n",[15,213,214,215,218],{},"The parent-owns-the-data rule has one consequence that trips up beginners: if a\nchild needs to trigger a change visible to the parent, it does so by calling a\n",[19,216,217],{},"callback function that the parent passed as a prop",". Data flows down; events\nflow up through callbacks.",[10,220,222],{"id":221},"function-components-vs-class-components","Function components vs class components",[15,224,225],{},"This is one of the most common React interview questions. The short answer: use\nfunction components — they cover everything except error boundaries.",[28,227,229],{"className":30,"code":228,"language":32,"meta":33,"style":33},"\u002F\u002F Function component (modern)\nfunction Counter() {\n  const [n, setN] = useState(0)\n  return \u003Cbutton onClick={() => setN(n + 1)}>{n}\u003C\u002Fbutton>\n}\n\n\u002F\u002F Class component (legacy)\nclass Counter extends React.Component {\n  state = { n: 0 }\n  render() {\n    return (\n      \u003Cbutton onClick={() => this.setState({ n: this.state.n + 1 })}>\n        {this.state.n}\n      \u003C\u002Fbutton>\n    )\n  }\n}\n",[35,230,231,236,246,279,319,323,327,332,354,370,377,384,423,434,444,450,456],{"__ignoreMap":33},[38,232,233],{"class":40,"line":41},[38,234,235],{"class":44},"\u002F\u002F Function component (modern)\n",[38,237,238,240,243],{"class":40,"line":48},[38,239,101],{"class":63},[38,241,242],{"class":59}," Counter",[38,244,245],{"class":51},"() {\n",[38,247,248,251,254,257,259,262,265,267,270,273,276],{"class":40,"line":85},[38,249,250],{"class":63},"  const",[38,252,253],{"class":51}," [",[38,255,256],{"class":55},"n",[38,258,114],{"class":51},[38,260,261],{"class":55},"setN",[38,263,264],{"class":51},"] ",[38,266,64],{"class":63},[38,268,269],{"class":59}," useState",[38,271,272],{"class":51},"(",[38,274,275],{"class":55},"0",[38,277,278],{"class":51},")\n",[38,280,281,283,286,289,292,294,297,300,303,306,309,312,315,317],{"class":40,"line":92},[38,282,131],{"class":63},[38,284,285],{"class":51}," \u003C",[38,287,288],{"class":143},"button",[38,290,291],{"class":59}," onClick",[38,293,64],{"class":63},[38,295,296],{"class":51},"{() ",[38,298,299],{"class":63},"=>",[38,301,302],{"class":59}," setN",[38,304,305],{"class":51},"(n ",[38,307,308],{"class":63},"+",[38,310,311],{"class":55}," 1",[38,313,314],{"class":51},")}>{n}\u003C\u002F",[38,316,288],{"class":143},[38,318,199],{"class":51},[38,320,321],{"class":40,"line":98},[38,322,211],{"class":51},[38,324,325],{"class":40,"line":128},[38,326,89],{"emptyLinePlaceholder":88},[38,328,329],{"class":40,"line":137},[38,330,331],{"class":44},"\u002F\u002F Class component (legacy)\n",[38,333,334,337,339,342,345,348,351],{"class":40,"line":175},[38,335,336],{"class":63},"class",[38,338,242],{"class":59},[38,340,341],{"class":63}," extends",[38,343,344],{"class":59}," React",[38,346,347],{"class":51},".",[38,349,350],{"class":59},"Component",[38,352,353],{"class":51}," {\n",[38,355,356,359,362,365,367],{"class":40,"line":191},[38,357,358],{"class":110},"  state",[38,360,361],{"class":63}," =",[38,363,364],{"class":51}," { n: ",[38,366,275],{"class":55},[38,368,369],{"class":51}," }\n",[38,371,372,375],{"class":40,"line":202},[38,373,374],{"class":59},"  render",[38,376,245],{"class":51},[38,378,379,382],{"class":40,"line":208},[38,380,381],{"class":63},"    return",[38,383,134],{"class":51},[38,385,387,389,391,393,395,397,399,402,404,407,410,413,416,418,420],{"class":40,"line":386},12,[38,388,178],{"class":51},[38,390,288],{"class":143},[38,392,291],{"class":59},[38,394,64],{"class":63},[38,396,296],{"class":51},[38,398,299],{"class":63},[38,400,401],{"class":55}," this",[38,403,347],{"class":51},[38,405,406],{"class":59},"setState",[38,408,409],{"class":51},"({ n: ",[38,411,412],{"class":55},"this",[38,414,415],{"class":51},".state.n ",[38,417,308],{"class":63},[38,419,311],{"class":55},[38,421,422],{"class":51}," })}>\n",[38,424,426,429,431],{"class":40,"line":425},13,[38,427,428],{"class":51},"        {",[38,430,412],{"class":55},[38,432,433],{"class":51},".state.n}\n",[38,435,437,440,442],{"class":40,"line":436},14,[38,438,439],{"class":51},"      \u003C\u002F",[38,441,288],{"class":143},[38,443,199],{"class":51},[38,445,447],{"class":40,"line":446},15,[38,448,449],{"class":51},"    )\n",[38,451,453],{"class":40,"line":452},16,[38,454,455],{"class":51},"  }\n",[38,457,459],{"class":40,"line":458},17,[38,460,211],{"class":51},[15,462,463],{},"The full comparison:",[465,466,467,483],"table",{},[468,469,470],"thead",{},[471,472,473,477,480],"tr",{},[474,475,476],"th",{},"Feature",[474,478,479],{},"Function",[474,481,482],{},"Class",[484,485,486,509,530,548,562],"tbody",{},[471,487,488,492,501],{},[489,490,491],"td",{},"State",[489,493,494,497,498],{},[35,495,496],{},"useState"," \u002F ",[35,499,500],{},"useReducer",[489,502,503,497,506],{},[35,504,505],{},"this.state",[35,507,508],{},"this.setState",[471,510,511,514,519],{},[489,512,513],{},"Lifecycle",[489,515,516],{},[35,517,518],{},"useEffect",[489,520,521,114,524,114,527],{},[35,522,523],{},"componentDidMount",[35,525,526],{},"componentDidUpdate",[35,528,529],{},"componentWillUnmount",[471,531,532,535,540],{},[489,533,534],{},"Context",[489,536,537],{},[35,538,539],{},"useContext",[489,541,542,497,545],{},[35,543,544],{},"static contextType",[35,546,547],{},"\u003CContext.Consumer>",[471,549,550,553,556],{},[489,551,552],{},"Error boundary",[489,554,555],{},"❌ Not supported",[489,557,558,559],{},"✅ ",[35,560,561],{},"componentDidCatch",[471,563,564,569,572],{},[489,565,566,568],{},[35,567,412],{}," binding issues",[489,570,571],{},"❌ None",[489,573,574],{},"✅ Must bind handlers",[15,576,577,580,581,583,584,587,588,591,592,595],{},[19,578,579],{},"The one remaining reason for class components:"," error boundaries. Only a class\ncomponent can implement ",[35,582,561],{}," and ",[35,585,586],{},"getDerivedStateFromError",". In\npractice, most teams write one ",[35,589,590],{},"\u003CErrorBoundary>"," class component and use\n",[35,593,594],{},"react-error-boundary"," everywhere else.",[10,597,599],{"id":598},"the-children-prop","The children prop",[15,601,602,603,606],{},"Any content placed between a component's opening and closing tags flows in as\nthe ",[35,604,605],{},"children"," prop. It's just a prop with special JSX syntax.",[28,608,610],{"className":30,"code":609,"language":32,"meta":33,"style":33},"function Card({ title, children }) {\n  return (\n    \u003Csection className=\"card\">\n      \u003Ch2>{title}\u003C\u002Fh2>\n      \u003Cdiv className=\"body\">{children}\u003C\u002Fdiv>\n    \u003C\u002Fsection>\n  )\n}\n\n\u002F\u002F The \u003Cp> and \u003Cbutton> become children\n\u003CCard title=\"Account\">\n  \u003Cp>Your subscription is active.\u003C\u002Fp>\n  \u003Cbutton>Manage\u003C\u002Fbutton>\n\u003C\u002FCard>\n",[35,611,612,630,636,652,665,685,693,697,701,705,710,727,741,754],{"__ignoreMap":33},[38,613,614,616,619,621,624,626,628],{"class":40,"line":41},[38,615,101],{"class":63},[38,617,618],{"class":59}," Card",[38,620,107],{"class":51},[38,622,623],{"class":110},"title",[38,625,114],{"class":51},[38,627,605],{"class":110},[38,629,125],{"class":51},[38,631,632,634],{"class":40,"line":48},[38,633,131],{"class":63},[38,635,134],{"class":51},[38,637,638,640,643,645,647,650],{"class":40,"line":85},[38,639,140],{"class":51},[38,641,642],{"class":143},"section",[38,644,147],{"class":59},[38,646,64],{"class":63},[38,648,649],{"class":67},"\"card\"",[38,651,199],{"class":51},[38,653,654,656,658,661,663],{"class":40,"line":92},[38,655,178],{"class":51},[38,657,10],{"class":143},[38,659,660],{"class":51},">{title}\u003C\u002F",[38,662,10],{"class":143},[38,664,199],{"class":51},[38,666,667,669,671,673,675,678,681,683],{"class":40,"line":98},[38,668,178],{"class":51},[38,670,144],{"class":143},[38,672,147],{"class":59},[38,674,64],{"class":63},[38,676,677],{"class":67},"\"body\"",[38,679,680],{"class":51},">{children}\u003C\u002F",[38,682,144],{"class":143},[38,684,199],{"class":51},[38,686,687,689,691],{"class":40,"line":128},[38,688,194],{"class":51},[38,690,642],{"class":143},[38,692,199],{"class":51},[38,694,695],{"class":40,"line":137},[38,696,205],{"class":51},[38,698,699],{"class":40,"line":175},[38,700,211],{"class":51},[38,702,703],{"class":40,"line":191},[38,704,89],{"emptyLinePlaceholder":88},[38,706,707],{"class":40,"line":202},[38,708,709],{"class":44},"\u002F\u002F The \u003Cp> and \u003Cbutton> become children\n",[38,711,712,714,717,720,722,725],{"class":40,"line":208},[38,713,52],{"class":51},[38,715,716],{"class":55},"Card",[38,718,719],{"class":59}," title",[38,721,64],{"class":63},[38,723,724],{"class":67},"\"Account\"",[38,726,199],{"class":51},[38,728,729,732,734,737,739],{"class":40,"line":386},[38,730,731],{"class":51},"  \u003C",[38,733,15],{"class":143},[38,735,736],{"class":51},">Your subscription is active.\u003C\u002F",[38,738,15],{"class":143},[38,740,199],{"class":51},[38,742,743,745,747,750,752],{"class":40,"line":425},[38,744,731],{"class":51},[38,746,288],{"class":143},[38,748,749],{"class":51},">Manage\u003C\u002F",[38,751,288],{"class":143},[38,753,199],{"class":51},[38,755,756,759,761],{"class":40,"line":436},[38,757,758],{"class":51},"\u003C\u002F",[38,760,716],{"class":55},[38,762,199],{"class":51},[15,764,765,767,768,771,772,774,775,778],{},[35,766,605],{}," enables ",[19,769,770],{},"composition"," — the ",[35,773,716],{}," component knows its shell but\nnothing about its contents. This is much more flexible than a data prop:\n",[35,776,777],{},"\u003CCard content={\u003Cp>…\u003C\u002Fp>} \u002F>"," works too, but the nested tag form reads better.",[15,780,781,783,784,787,788,791],{},[35,782,605],{}," can be: a string, a single element, an array of elements, a\nfunction (render prop), or ",[35,785,786],{},"undefined",". Use ",[35,789,790],{},"React.Children.count(children)","\nto check how many children were passed.",[10,793,795],{"id":794},"default-props","Default props",[15,797,798],{},"The idiomatic modern approach is default parameter destructuring:",[28,800,802],{"className":30,"code":801,"language":32,"meta":33,"style":33},"function Button({ label = 'Submit', variant = 'primary', disabled = false }) {\n  return (\n    \u003Cbutton className={`btn btn-${variant}`} disabled={disabled}>\n      {label}\n    \u003C\u002Fbutton>\n  )\n}\n",[35,803,804,843,849,879,884,892,896],{"__ignoreMap":33},[38,805,806,808,811,813,816,818,821,823,826,828,831,833,836,838,841],{"class":40,"line":41},[38,807,101],{"class":63},[38,809,810],{"class":59}," Button",[38,812,107],{"class":51},[38,814,815],{"class":110},"label",[38,817,361],{"class":63},[38,819,820],{"class":67}," 'Submit'",[38,822,114],{"class":51},[38,824,825],{"class":110},"variant",[38,827,361],{"class":63},[38,829,830],{"class":67}," 'primary'",[38,832,114],{"class":51},[38,834,835],{"class":110},"disabled",[38,837,361],{"class":63},[38,839,840],{"class":55}," false",[38,842,125],{"class":51},[38,844,845,847],{"class":40,"line":48},[38,846,131],{"class":63},[38,848,134],{"class":51},[38,850,851,853,855,857,859,861,864,866,869,872,874,876],{"class":40,"line":85},[38,852,140],{"class":51},[38,854,288],{"class":143},[38,856,147],{"class":59},[38,858,64],{"class":63},[38,860,152],{"class":51},[38,862,863],{"class":67},"`btn btn-${",[38,865,825],{"class":51},[38,867,868],{"class":67},"}`",[38,870,871],{"class":51},"} ",[38,873,835],{"class":59},[38,875,64],{"class":63},[38,877,878],{"class":51},"{disabled}>\n",[38,880,881],{"class":40,"line":92},[38,882,883],{"class":51},"      {label}\n",[38,885,886,888,890],{"class":40,"line":98},[38,887,194],{"class":51},[38,889,288],{"class":143},[38,891,199],{"class":51},[38,893,894],{"class":40,"line":128},[38,895,205],{"class":51},[38,897,898],{"class":40,"line":137},[38,899,211],{"class":51},[15,901,902,903,906],{},"This is co-located with the parameter list and works with TypeScript type\nannotations without any React-specific API. The legacy ",[35,904,905],{},"Button.defaultProps","\nobject still works but is considered outdated and may be removed in a future\nReact version.",[10,908,910],{"id":909},"proptypes","PropTypes",[15,912,913,915,916,919],{},[35,914,910],{}," is a runtime prop validation library (separate ",[35,917,918],{},"prop-types"," package)\nthat logs warnings in development when props fail the declared type:",[28,921,923],{"className":30,"code":922,"language":32,"meta":33,"style":33},"import PropTypes from 'prop-types'\n\nfunction Avatar({ src, alt, size }) {\n  return \u003Cimg src={src} alt={alt} width={size} height={size} \u002F>\n}\n\nAvatar.propTypes = {\n  src: PropTypes.string.isRequired,\n  alt: PropTypes.string.isRequired,\n  size: PropTypes.number,\n}\n\nAvatar.defaultProps = { size: 48 }\n",[35,924,925,939,943,967,1007,1011,1015,1024,1029,1034,1039,1043,1047],{"__ignoreMap":33},[38,926,927,930,933,936],{"class":40,"line":41},[38,928,929],{"class":63},"import",[38,931,932],{"class":51}," PropTypes ",[38,934,935],{"class":63},"from",[38,937,938],{"class":67}," 'prop-types'\n",[38,940,941],{"class":40,"line":48},[38,942,89],{"emptyLinePlaceholder":88},[38,944,945,947,950,952,955,957,960,962,965],{"class":40,"line":85},[38,946,101],{"class":63},[38,948,949],{"class":59}," Avatar",[38,951,107],{"class":51},[38,953,954],{"class":110},"src",[38,956,114],{"class":51},[38,958,959],{"class":110},"alt",[38,961,114],{"class":51},[38,963,964],{"class":110},"size",[38,966,125],{"class":51},[38,968,969,971,973,976,979,981,984,986,988,991,994,996,999,1002,1004],{"class":40,"line":92},[38,970,131],{"class":63},[38,972,285],{"class":51},[38,974,975],{"class":143},"img",[38,977,978],{"class":59}," src",[38,980,64],{"class":63},[38,982,983],{"class":51},"{src} ",[38,985,959],{"class":59},[38,987,64],{"class":63},[38,989,990],{"class":51},"{alt} ",[38,992,993],{"class":59},"width",[38,995,64],{"class":63},[38,997,998],{"class":51},"{size} ",[38,1000,1001],{"class":59},"height",[38,1003,64],{"class":63},[38,1005,1006],{"class":51},"{size} \u002F>\n",[38,1008,1009],{"class":40,"line":98},[38,1010,211],{"class":51},[38,1012,1013],{"class":40,"line":128},[38,1014,89],{"emptyLinePlaceholder":88},[38,1016,1017,1020,1022],{"class":40,"line":137},[38,1018,1019],{"class":51},"Avatar.propTypes ",[38,1021,64],{"class":63},[38,1023,353],{"class":51},[38,1025,1026],{"class":40,"line":175},[38,1027,1028],{"class":51},"  src: PropTypes.string.isRequired,\n",[38,1030,1031],{"class":40,"line":191},[38,1032,1033],{"class":51},"  alt: PropTypes.string.isRequired,\n",[38,1035,1036],{"class":40,"line":202},[38,1037,1038],{"class":51},"  size: PropTypes.number,\n",[38,1040,1041],{"class":40,"line":208},[38,1042,211],{"class":51},[38,1044,1045],{"class":40,"line":386},[38,1046,89],{"emptyLinePlaceholder":88},[38,1048,1049,1052,1054,1057,1060],{"class":40,"line":425},[38,1050,1051],{"class":51},"Avatar.defaultProps ",[38,1053,64],{"class":63},[38,1055,1056],{"class":51}," { size: ",[38,1058,1059],{"class":55},"48",[38,1061,369],{"class":51},[15,1063,1064],{},"The trade-off with TypeScript: PropTypes catch mistakes at runtime in development;\nTypeScript catches them at compile time. In a TypeScript project, TypeScript alone\nis sufficient. In a plain JavaScript project, PropTypes are a lightweight safety\nnet.",[10,1066,1068],{"id":1067},"props-vs-state","Props vs state",[465,1070,1071,1082],{},[468,1072,1073],{},[471,1074,1075,1077,1080],{},[474,1076],{},[474,1078,1079],{},"Props",[474,1081,491],{},[484,1083,1084,1095,1109],{},[471,1085,1086,1089,1092],{},[489,1087,1088],{},"Owned by",[489,1090,1091],{},"Parent",[489,1093,1094],{},"The component itself",[471,1096,1097,1100,1103],{},[489,1098,1099],{},"Mutable by",[489,1101,1102],{},"Parent only",[489,1104,1105,1106,1108],{},"The component (",[35,1107,406],{}," \u002F setter)",[471,1110,1111,1114,1117],{},[489,1112,1113],{},"Purpose",[489,1115,1116],{},"Pass configuration in",[489,1118,1119],{},"Track data that changes",[15,1121,1122,1123,1126,1127,1130],{},"A useful mental model: ",[19,1124,1125],{},"props are like function arguments"," (passed in, fixed\nper call); ",[19,1128,1129],{},"state is like local variables"," that persist between calls.",[28,1132,1134],{"className":30,"code":1133,"language":32,"meta":33,"style":33},"function Thermometer({ unit }) {      \u002F\u002F unit is a prop\n  const [temp, setTemp] = useState(20) \u002F\u002F temp is state\n  return (\n    \u003Cdiv>\n      {temp}°{unit}\n      \u003Cbutton onClick={() => setTemp(t => t + 1)}>+\u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n  )\n}\n",[35,1135,1136,1154,1185,1191,1199,1204,1243,1251,1255],{"__ignoreMap":33},[38,1137,1138,1140,1143,1145,1148,1151],{"class":40,"line":41},[38,1139,101],{"class":63},[38,1141,1142],{"class":59}," Thermometer",[38,1144,107],{"class":51},[38,1146,1147],{"class":110},"unit",[38,1149,1150],{"class":51}," }) {      ",[38,1152,1153],{"class":44},"\u002F\u002F unit is a prop\n",[38,1155,1156,1158,1160,1163,1165,1168,1170,1172,1174,1176,1179,1182],{"class":40,"line":48},[38,1157,250],{"class":63},[38,1159,253],{"class":51},[38,1161,1162],{"class":55},"temp",[38,1164,114],{"class":51},[38,1166,1167],{"class":55},"setTemp",[38,1169,264],{"class":51},[38,1171,64],{"class":63},[38,1173,269],{"class":59},[38,1175,272],{"class":51},[38,1177,1178],{"class":55},"20",[38,1180,1181],{"class":51},") ",[38,1183,1184],{"class":44},"\u002F\u002F temp is state\n",[38,1186,1187,1189],{"class":40,"line":85},[38,1188,131],{"class":63},[38,1190,134],{"class":51},[38,1192,1193,1195,1197],{"class":40,"line":92},[38,1194,140],{"class":51},[38,1196,144],{"class":143},[38,1198,199],{"class":51},[38,1200,1201],{"class":40,"line":98},[38,1202,1203],{"class":51},"      {temp}°{unit}\n",[38,1205,1206,1208,1210,1212,1214,1216,1218,1221,1223,1226,1229,1232,1234,1236,1239,1241],{"class":40,"line":128},[38,1207,178],{"class":51},[38,1209,288],{"class":143},[38,1211,291],{"class":59},[38,1213,64],{"class":63},[38,1215,296],{"class":51},[38,1217,299],{"class":63},[38,1219,1220],{"class":59}," setTemp",[38,1222,272],{"class":51},[38,1224,1225],{"class":110},"t",[38,1227,1228],{"class":63}," =>",[38,1230,1231],{"class":51}," t ",[38,1233,308],{"class":63},[38,1235,311],{"class":55},[38,1237,1238],{"class":51},")}>+\u003C\u002F",[38,1240,288],{"class":143},[38,1242,199],{"class":51},[38,1244,1245,1247,1249],{"class":40,"line":137},[38,1246,194],{"class":51},[38,1248,144],{"class":143},[38,1250,199],{"class":51},[38,1252,1253],{"class":40,"line":175},[38,1254,205],{"class":51},[38,1256,1257],{"class":40,"line":191},[38,1258,211],{"class":51},[10,1260,1262],{"id":1261},"prop-drilling-and-how-to-avoid-it","Prop drilling and how to avoid it",[15,1264,1265],{},"Prop drilling happens when you pass a prop through several components that don't\nuse it — just to get it to a distant descendant.",[28,1267,1269],{"className":30,"code":1268,"language":32,"meta":33,"style":33},"\u002F\u002F Drilling `user` through Layout and Sidebar just to reach Avatar\n\u003CApp user={user}>\n  \u003CLayout user={user}>\n    \u003CSidebar user={user}>\n      \u003CAvatar user={user} \u002F>\n    \u003C\u002FSidebar>\n  \u003C\u002FLayout>\n\u003C\u002FApp>\n",[35,1270,1271,1276,1291,1304,1317,1331,1339,1348],{"__ignoreMap":33},[38,1272,1273],{"class":40,"line":41},[38,1274,1275],{"class":44},"\u002F\u002F Drilling `user` through Layout and Sidebar just to reach Avatar\n",[38,1277,1278,1280,1283,1286,1288],{"class":40,"line":48},[38,1279,52],{"class":51},[38,1281,1282],{"class":55},"App",[38,1284,1285],{"class":59}," user",[38,1287,64],{"class":63},[38,1289,1290],{"class":51},"{user}>\n",[38,1292,1293,1295,1298,1300,1302],{"class":40,"line":85},[38,1294,731],{"class":51},[38,1296,1297],{"class":55},"Layout",[38,1299,1285],{"class":59},[38,1301,64],{"class":63},[38,1303,1290],{"class":51},[38,1305,1306,1308,1311,1313,1315],{"class":40,"line":92},[38,1307,140],{"class":51},[38,1309,1310],{"class":55},"Sidebar",[38,1312,1285],{"class":59},[38,1314,64],{"class":63},[38,1316,1290],{"class":51},[38,1318,1319,1321,1324,1326,1328],{"class":40,"line":98},[38,1320,178],{"class":51},[38,1322,1323],{"class":55},"Avatar",[38,1325,1285],{"class":59},[38,1327,64],{"class":63},[38,1329,1330],{"class":51},"{user} \u002F>\n",[38,1332,1333,1335,1337],{"class":40,"line":128},[38,1334,194],{"class":51},[38,1336,1310],{"class":55},[38,1338,199],{"class":51},[38,1340,1341,1344,1346],{"class":40,"line":137},[38,1342,1343],{"class":51},"  \u003C\u002F",[38,1345,1297],{"class":55},[38,1347,199],{"class":51},[38,1349,1350,1352,1354],{"class":40,"line":175},[38,1351,758],{"class":51},[38,1353,1282],{"class":55},[38,1355,199],{"class":51},[15,1357,1358],{},"Alternatives:",[1360,1361,1362,1387,1399],"ol",{},[1363,1364,1365,1368,1369,1372,1373,1375,1376,583,1378,1380,1381,1383,1384,347],"li",{},[19,1366,1367],{},"Composition with children"," — pass ",[35,1370,1371],{},"\u003CAvatar user={user} \u002F>"," as a child\nof ",[35,1374,1282],{},"; ",[35,1377,1297],{},[35,1379,1310],{}," receive it as ",[35,1382,605],{}," and never see ",[35,1385,1386],{},"user",[1363,1388,1389,1391,1392,1395,1396,1398],{},[19,1390,534],{}," — ",[35,1393,1394],{},"React.createContext"," + ",[35,1397,539],{}," for genuinely global data\n(current user, theme, locale).",[1363,1400,1401,1404],{},[19,1402,1403],{},"State management"," — Zustand, Redux for data needed by many unrelated components.",[15,1406,1407],{},"Before reaching for Context, try restructuring with composition — it's often\nsimpler and the data flow stays explicit.",[10,1409,1411],{"id":1410},"spread-props-pattern","Spread props pattern",[15,1413,1414],{},"Forward a batch of unknown props to a child without listing them:",[28,1416,1418],{"className":30,"code":1417,"language":32,"meta":33,"style":33},"function TextInput({ label, error, ...inputProps }) {\n  return (\n    \u003Cdiv>\n      \u003Clabel>{label}\u003C\u002Flabel>\n      \u003Cinput {...inputProps} \u002F>\n      {error && \u003Cspan className=\"error\">{error}\u003C\u002Fspan>}\n    \u003C\u002Fdiv>\n  )\n}\n\n\u002F\u002F All native \u003Cinput> attributes work without boilerplate\n\u003CTextInput label=\"Email\" type=\"email\" name=\"email\" required error={errors.email} \u002F>\n",[35,1419,1420,1446,1452,1460,1473,1488,1515,1523,1527,1531,1535,1540],{"__ignoreMap":33},[38,1421,1422,1424,1427,1429,1431,1433,1436,1438,1441,1444],{"class":40,"line":41},[38,1423,101],{"class":63},[38,1425,1426],{"class":59}," TextInput",[38,1428,107],{"class":51},[38,1430,815],{"class":110},[38,1432,114],{"class":51},[38,1434,1435],{"class":110},"error",[38,1437,114],{"class":51},[38,1439,1440],{"class":63},"...",[38,1442,1443],{"class":110},"inputProps",[38,1445,125],{"class":51},[38,1447,1448,1450],{"class":40,"line":48},[38,1449,131],{"class":63},[38,1451,134],{"class":51},[38,1453,1454,1456,1458],{"class":40,"line":85},[38,1455,140],{"class":51},[38,1457,144],{"class":143},[38,1459,199],{"class":51},[38,1461,1462,1464,1466,1469,1471],{"class":40,"line":92},[38,1463,178],{"class":51},[38,1465,815],{"class":143},[38,1467,1468],{"class":51},">{label}\u003C\u002F",[38,1470,815],{"class":143},[38,1472,199],{"class":51},[38,1474,1475,1477,1480,1483,1485],{"class":40,"line":98},[38,1476,178],{"class":51},[38,1478,1479],{"class":143},"input",[38,1481,1482],{"class":51}," {",[38,1484,1440],{"class":63},[38,1486,1487],{"class":51},"inputProps} \u002F>\n",[38,1489,1490,1493,1496,1498,1500,1502,1504,1507,1510,1512],{"class":40,"line":128},[38,1491,1492],{"class":51},"      {error ",[38,1494,1495],{"class":63},"&&",[38,1497,285],{"class":51},[38,1499,38],{"class":143},[38,1501,147],{"class":59},[38,1503,64],{"class":63},[38,1505,1506],{"class":67},"\"error\"",[38,1508,1509],{"class":51},">{error}\u003C\u002F",[38,1511,38],{"class":143},[38,1513,1514],{"class":51},">}\n",[38,1516,1517,1519,1521],{"class":40,"line":137},[38,1518,194],{"class":51},[38,1520,144],{"class":143},[38,1522,199],{"class":51},[38,1524,1525],{"class":40,"line":175},[38,1526,205],{"class":51},[38,1528,1529],{"class":40,"line":191},[38,1530,211],{"class":51},[38,1532,1533],{"class":40,"line":202},[38,1534,89],{"emptyLinePlaceholder":88},[38,1536,1537],{"class":40,"line":208},[38,1538,1539],{"class":44},"\u002F\u002F All native \u003Cinput> attributes work without boilerplate\n",[38,1541,1542,1544,1547,1550,1552,1555,1558,1560,1563,1565,1567,1569,1572,1575,1577],{"class":40,"line":386},[38,1543,52],{"class":51},[38,1545,1546],{"class":55},"TextInput",[38,1548,1549],{"class":59}," label",[38,1551,64],{"class":63},[38,1553,1554],{"class":67},"\"Email\"",[38,1556,1557],{"class":59}," type",[38,1559,64],{"class":63},[38,1561,1562],{"class":67},"\"email\"",[38,1564,60],{"class":59},[38,1566,64],{"class":63},[38,1568,1562],{"class":67},[38,1570,1571],{"class":59}," required",[38,1573,1574],{"class":59}," error",[38,1576,64],{"class":63},[38,1578,1579],{"class":51},"{errors.email} \u002F>\n",[15,1581,1582],{},"Always destructure known props first, then spread the rest. Spreading the entire\nprops object onto a DOM element can forward non-standard props, which React warns\nabout.",[10,1584,1586],{"id":1585},"composition-over-inheritance","Composition over inheritance",[15,1588,1589],{},"React's component model is built on composition, not inheritance. The docs\nexplicitly discourage using class inheritance between your own components.",[28,1591,1593],{"className":30,"code":1592,"language":32,"meta":33,"style":33},"\u002F\u002F ✅ Composition — SuccessDialog wraps Dialog\nfunction SuccessDialog({ message }) {\n  return (\n    \u003CDialog icon=\"check\" title=\"Done\">\n      \u003Cp>{message}\u003C\u002Fp>\n    \u003C\u002FDialog>\n  )\n}\n\n\u002F\u002F ❌ Inheritance — unusual and discouraged\nclass SuccessDialog extends Dialog { … }\n",[35,1594,1595,1600,1614,1620,1644,1657,1665,1669,1673,1677,1682],{"__ignoreMap":33},[38,1596,1597],{"class":40,"line":41},[38,1598,1599],{"class":44},"\u002F\u002F ✅ Composition — SuccessDialog wraps Dialog\n",[38,1601,1602,1604,1607,1609,1612],{"class":40,"line":48},[38,1603,101],{"class":63},[38,1605,1606],{"class":59}," SuccessDialog",[38,1608,107],{"class":51},[38,1610,1611],{"class":110},"message",[38,1613,125],{"class":51},[38,1615,1616,1618],{"class":40,"line":85},[38,1617,131],{"class":63},[38,1619,134],{"class":51},[38,1621,1622,1624,1627,1630,1632,1635,1637,1639,1642],{"class":40,"line":92},[38,1623,140],{"class":51},[38,1625,1626],{"class":55},"Dialog",[38,1628,1629],{"class":59}," icon",[38,1631,64],{"class":63},[38,1633,1634],{"class":67},"\"check\"",[38,1636,719],{"class":59},[38,1638,64],{"class":63},[38,1640,1641],{"class":67},"\"Done\"",[38,1643,199],{"class":51},[38,1645,1646,1648,1650,1653,1655],{"class":40,"line":98},[38,1647,178],{"class":51},[38,1649,15],{"class":143},[38,1651,1652],{"class":51},">{message}\u003C\u002F",[38,1654,15],{"class":143},[38,1656,199],{"class":51},[38,1658,1659,1661,1663],{"class":40,"line":128},[38,1660,194],{"class":51},[38,1662,1626],{"class":55},[38,1664,199],{"class":51},[38,1666,1667],{"class":40,"line":137},[38,1668,205],{"class":51},[38,1670,1671],{"class":40,"line":175},[38,1672,211],{"class":51},[38,1674,1675],{"class":40,"line":191},[38,1676,89],{"emptyLinePlaceholder":88},[38,1678,1679],{"class":40,"line":202},[38,1680,1681],{"class":44},"\u002F\u002F ❌ Inheritance — unusual and discouraged\n",[38,1683,1684,1686,1688,1690,1693],{"class":40,"line":208},[38,1685,336],{"class":63},[38,1687,1606],{"class":59},[38,1689,341],{"class":63},[38,1691,1692],{"class":59}," Dialog",[38,1694,1695],{"class":51}," { … }\n",[15,1697,1698],{},"Composition strategies:",[1700,1701,1702,1708,1714],"ul",{},[1363,1703,1704,1707],{},[19,1705,1706],{},"Children prop"," — generic shell that accepts any content.",[1363,1709,1710,1713],{},[19,1711,1712],{},"Specialized wrappers"," — one component renders another with pre-set props.",[1363,1715,1716,1719],{},[19,1717,1718],{},"Render props \u002F hooks"," — share logic without shared structure.",[15,1721,1722,1725],{},[19,1723,1724],{},"Rule of thumb:"," when you think \"I want a component like X but with Y\nchanged,\" reach for a wrapper with props or children before reaching for a\nclass hierarchy.",[10,1727,1729],{"id":1728},"controlled-components","Controlled components",[15,1731,1732],{},"A controlled component's form value is driven entirely by React state. React\nbecomes the single source of truth.",[28,1734,1736],{"className":30,"code":1735,"language":32,"meta":33,"style":33},"function EmailInput() {\n  const [email, setEmail] = useState('')\n  return (\n    \u003Cinput\n      type=\"email\"\n      value={email}\n      onChange={e => setEmail(e.target.value)}\n    \u002F>\n  )\n}\n",[35,1737,1738,1747,1774,1780,1787,1797,1807,1827,1832,1836],{"__ignoreMap":33},[38,1739,1740,1742,1745],{"class":40,"line":41},[38,1741,101],{"class":63},[38,1743,1744],{"class":59}," EmailInput",[38,1746,245],{"class":51},[38,1748,1749,1751,1753,1756,1758,1761,1763,1765,1767,1769,1772],{"class":40,"line":48},[38,1750,250],{"class":63},[38,1752,253],{"class":51},[38,1754,1755],{"class":55},"email",[38,1757,114],{"class":51},[38,1759,1760],{"class":55},"setEmail",[38,1762,264],{"class":51},[38,1764,64],{"class":63},[38,1766,269],{"class":59},[38,1768,272],{"class":51},[38,1770,1771],{"class":67},"''",[38,1773,278],{"class":51},[38,1775,1776,1778],{"class":40,"line":85},[38,1777,131],{"class":63},[38,1779,134],{"class":51},[38,1781,1782,1784],{"class":40,"line":92},[38,1783,140],{"class":51},[38,1785,1786],{"class":143},"input\n",[38,1788,1789,1792,1794],{"class":40,"line":98},[38,1790,1791],{"class":59},"      type",[38,1793,64],{"class":63},[38,1795,1796],{"class":67},"\"email\"\n",[38,1798,1799,1802,1804],{"class":40,"line":128},[38,1800,1801],{"class":59},"      value",[38,1803,64],{"class":63},[38,1805,1806],{"class":51},"{email}\n",[38,1808,1809,1812,1814,1816,1819,1821,1824],{"class":40,"line":137},[38,1810,1811],{"class":59},"      onChange",[38,1813,64],{"class":63},[38,1815,152],{"class":51},[38,1817,1818],{"class":110},"e",[38,1820,1228],{"class":63},[38,1822,1823],{"class":59}," setEmail",[38,1825,1826],{"class":51},"(e.target.value)}\n",[38,1828,1829],{"class":40,"line":175},[38,1830,1831],{"class":51},"    \u002F>\n",[38,1833,1834],{"class":40,"line":191},[38,1835,205],{"class":51},[38,1837,1838],{"class":40,"line":202},[38,1839,211],{"class":51},[15,1841,1842,1843,1845,1846,1849,1850,1853],{},"Every keystroke calls ",[35,1844,1760],{},", which updates state, which re-renders, which\nsets ",[35,1847,1848],{},"value"," — a tight loop. The payoff: you can validate or transform input on\nevery change, and programmatic resets work (",[35,1851,1852],{},"setEmail('')"," clears the field).",[15,1855,1856,1857,1860],{},"Uncontrolled components let the DOM own the value, accessed via ",[35,1858,1859],{},"useRef"," at\nsubmission time. Use them when the form is simple and you only need values at\nsubmit.",[10,1862,1864],{"id":1863},"what-interviewers-are-testing","What interviewers are testing",[15,1866,1867,1868,1871],{},"Props questions check whether you understand the ",[19,1869,1870],{},"unidirectional data flow","\ncontract that makes React predictable. Class-vs-function questions check whether\nyou know modern React. Children and composition questions check whether you reach\nfor the right tool instead of prop-drilling or inheritance.",[15,1873,1874],{},"Know the read-only rule, the flow-down principle, and why function components\nreplaced classes for all but error boundaries — and you'll answer this category\nconfidently.",[1876,1877,1878],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}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 .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}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);}",{"title":33,"searchDepth":48,"depth":48,"links":1880},[1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891],{"id":12,"depth":48,"text":13},{"id":221,"depth":48,"text":222},{"id":598,"depth":48,"text":599},{"id":794,"depth":48,"text":795},{"id":909,"depth":48,"text":910},{"id":1067,"depth":48,"text":1068},{"id":1261,"depth":48,"text":1262},{"id":1410,"depth":48,"text":1411},{"id":1585,"depth":48,"text":1586},{"id":1728,"depth":48,"text":1729},{"id":1863,"depth":48,"text":1864},"React props and component types interview questions — function vs class components, children, defaultProps, PropTypes, composition over inheritance, and controlled components.","easy","md","React","react",{"subtopicSlug":1898},"props-component-types","\u002Fblog\u002Freact-props-component-types-guide","\u002Freact\u002Fcomponents\u002Fprops-component-types",{"title":5,"description":1892},"blog\u002Freact-props-component-types-guide","Props and Component Types","Components","components","2026-06-23","Xc_UeoadfCjuagGED0zFloCj-QoHF_SenPD6YH0U0B4",1782244083351]