[{"data":1,"prerenderedAt":1093},["ShallowReactive",2],{"content:\u002Fframework-performance\u002Freact-rendering-performance\u002Ffinding-wasted-renders-with-the-react-profiler":3,"surroundings:\u002Fframework-performance\u002Freact-rendering-performance\u002Ffinding-wasted-renders-with-the-react-profiler":1084},{"id":4,"title":5,"body":6,"description":1063,"extension":1064,"meta":1065,"navigation":1077,"path":1078,"seo":1079,"stem":1082,"__hash__":1083},"content\u002Fframework-performance\u002Freact-rendering-performance\u002Ffinding-wasted-renders-with-the-react-profiler\u002Findex.md","Finding Wasted Renders with the React Profiler",{"type":7,"value":8,"toc":1045},"minimark",[9,14,29,32,180,185,219,223,229,235,241,247,251,256,259,263,266,270,273,435,439,442,574,578,581,585,607,611,625,781,831,835,838,842,868,872,878,884,890,900,904,916,925,934,943,952,961,970,985,994,1003,1007,1030,1035,1038,1041],[10,11,13],"h1",{"id":12},"how-to-find-wasted-renders-with-the-react-profiler","How to Find Wasted Renders with the React Profiler",[15,16,17,18,23,24,28],"p",{},"This guide is part of ",[19,20,22],"a",{"href":21},"\u002Fframework-performance\u002Freact-rendering-performance\u002F","React Rendering Performance",", within ",[19,25,27],{"href":26},"\u002Fframework-performance\u002F","Framework Performance",". When a React interaction feels slow, the question is always: which components rendered, why, and how long did each take? The React DevTools Profiler answers all three. It records every commit during a session, showing each component's render time, whether it rendered at all, and — with the right setting enabled — the reason it rendered: changed props, changed state, changed context, or a parent re-render.",[15,30,31],{},"Wasted renders — components that re-render without any change in output — are the most common React performance problem, and the Profiler makes them visible in minutes. Combined with the browser's Performance panel for total interaction cost, it turns vague slowness into a short list of components to fix.",[15,33,34],{},[35,36,42,43,42,50,42,54,42,57,42,75,42,83,42,89,42,97,42,104,42,109,42,113,42,116,42,120,42,123,42,126,42,130,42,133,42,139,42,143,42,146,42,149,42,152,42,156,42,159,42,168,42,172,42,176,42],"svg",{"viewBox":37,"width":38,"role":39,"ariaLabel":40,"style":41},"0 0 760 149","100%","img","Steps for using the React Profiler to find and fix wasted renders.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[44,45],"rect",{"className":46,"x":48,"y":48,"width":38,"height":38,"fill":49},[47],"svg-canvas","0","#ffffff",[51,52,53],"title",{},"Profiler workflow",[55,56,40],"desc",{},[58,59,60],"defs",{},[61,62,69],"marker",{"id":63,"viewBox":64,"refX":65,"refY":66,"markerWidth":67,"markerHeight":67,"orient":68},"faf55fac6e","0 0 10 10","9","5","7","auto-start-reverse",[70,71],"path",{"d":72,"fill":73,"style":74},"M0 0 L10 5 L0 10 z","currentColor","fill-opacity:0.7",[44,76],{"x":77,"y":77,"width":78,"height":79,"rx":80,"fill":81,"stroke":73,"style":82},"1","758","147","10","none","stroke-opacity:0.18",[84,85,53],"text",{"x":86,"y":87,"fill":73,"style":88},"28.0","34.0","font-size:16px;font-weight:700",[44,90],{"x":86,"y":91,"width":92,"height":93,"rx":94,"fill":95,"stroke":95,"style":96},"56.0","108.8","71.0","6","#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[84,98,103],{"x":99,"y":100,"fill":73,"style":101,"textAnchor":102},"82.4","78.0","font-size:13px;font-weight:700","middle","Enable reasons",[84,105,108],{"x":99,"y":106,"fill":73,"style":107,"textAnchor":102},"96.0","font-size:12px","why each",[84,110,112],{"x":99,"y":111,"fill":73,"style":107,"textAnchor":102},"112.0","rendered",[44,114],{"x":115,"y":91,"width":92,"height":93,"rx":94,"fill":95,"stroke":95,"style":96},"176.8",[84,117,119],{"x":118,"y":100,"fill":73,"style":101,"textAnchor":102},"231.2","Record",[84,121,122],{"x":118,"y":106,"fill":73,"style":107,"textAnchor":102},"one interaction",[44,124],{"x":125,"y":91,"width":92,"height":93,"rx":94,"fill":95,"stroke":95,"style":96},"325.6",[84,127,129],{"x":128,"y":100,"fill":73,"style":101,"textAnchor":102},"380.0","Ranked view",[84,131,132],{"x":128,"y":106,"fill":73,"style":107,"textAnchor":102},"most expensive",[44,134],{"x":135,"y":91,"width":92,"height":93,"rx":94,"fill":136,"stroke":137,"style":138},"474.4","#ffc300","#b8860b","fill-opacity:0.24;stroke-opacity:0.9",[84,140,142],{"x":141,"y":100,"fill":73,"style":101,"textAnchor":102},"528.8","Read reasons",[84,144,145],{"x":141,"y":106,"fill":73,"style":107,"textAnchor":102},"props, context,",[84,147,148],{"x":141,"y":111,"fill":73,"style":107,"textAnchor":102},"parent",[44,150],{"x":151,"y":91,"width":92,"height":93,"rx":94,"fill":95,"stroke":95,"style":96},"623.2",[84,153,155],{"x":154,"y":100,"fill":73,"style":101,"textAnchor":102},"677.6","Fix + re-record",[84,157,158],{"x":154,"y":106,"fill":73,"style":107,"textAnchor":102},"compare commits",[160,161],"line",{"x1":162,"y1":163,"x2":164,"y2":163,"stroke":73,"strokeWidth":165,"style":166,"markerEnd":167},"136.8","91.5","174.8","1.5","stroke-opacity:0.6","url(#faf55fac6e)",[160,169],{"x1":170,"y1":163,"x2":171,"y2":163,"stroke":73,"strokeWidth":165,"style":166,"markerEnd":167},"285.6","323.6",[160,173],{"x1":174,"y1":163,"x2":175,"y2":163,"stroke":73,"strokeWidth":165,"style":166,"markerEnd":167},"434.4","472.4",[160,177],{"x1":178,"y1":163,"x2":179,"y2":163,"stroke":73,"strokeWidth":165,"style":166,"markerEnd":167},"583.2","621.2",[181,182,184],"h2",{"id":183},"rapid-diagnosis","Rapid Diagnosis",[186,187,188,196,202,208],"ul",{},[189,190,191,195],"li",{},[192,193,194],"strong",{},"Install React DevTools"," and open the Profiler tab.",[189,197,198,201],{},[192,199,200],{},"Enable \"Record why each component rendered while profiling\""," in the Profiler settings (gear icon).",[189,203,204,207],{},[192,205,206],{},"Enable \"Highlight updates when components render\""," in Components settings for a quick visual check.",[189,209,210,213,214,218],{},[192,211,212],{},"Use a production profiling build"," (",[215,216,217],"code",{},"react-dom\u002Fprofiling",") for realistic timings on deployed sites.",[181,220,222],{"id":221},"root-cause-analysis-common-wasted-render-sources","Root Cause Analysis: Common Wasted Render Sources",[15,224,225,228],{},[192,226,227],{},"1. Parent re-renders."," Children re-render because the parent did, with identical props.",[15,230,231,234],{},[192,232,233],{},"2. Unstable props."," New objects, arrays or callbacks created each render defeat memoization.",[15,236,237,240],{},[192,238,239],{},"3. Broad context."," A context value changes, re-rendering every consumer.",[15,242,243,246],{},[192,244,245],{},"4. State too high."," Local state in a high component re-renders its whole subtree.",[181,248,250],{"id":249},"step-by-step-resolution","Step-by-Step Resolution",[252,253,255],"h3",{"id":254},"_1-record-one-interaction-at-a-time","1. Record one interaction at a time",[15,257,258],{},"Start recording, perform a single interaction (type one character, click one filter), stop. Short recordings make commits easy to read.",[252,260,262],{"id":261},"_2-read-the-flame-and-ranked-charts","2. Read the flame and ranked charts",[15,264,265],{},"The flame chart shows the tree for a commit: wide, yellow components took longest; grey components did not render. The ranked chart sorts components by render time. Start with the top entries.",[252,267,269],{"id":268},"_3-check-why-each-component-rendered","3. Check why each component rendered",[15,271,272],{},"Select a component: the right panel lists \"Why did this render?\" — for example \"Props changed: (onSelect)\", \"Context changed\", or \"The parent component rendered\". Unstable callbacks and objects appear as changed props even when their content is the same.",[274,275,280],"pre",{"className":276,"code":277,"language":278,"meta":279,"style":279},"language-javascript shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","\u002F\u002F Profiler says: \"Props changed: (filters)\". The filters object is recreated each render.\nfunction Page() {\n  const [sort, setSort] = useState('price');\n  const filters = useMemo(() => ({ inStock: true, category: 'shoes' }), []);  \u002F\u002F stable identity\n  return \u003CProductList filters={filters} sort={sort} \u002F>;\n}\n\u002F\u002F trade-off: useMemo only helps if ProductList is memoized (React.memo) or uses\n\u002F\u002F filters in an effect dependency; otherwise it adds overhead for nothing.\n","javascript","",[215,281,282,290,305,343,381,417,423,429],{"__ignoreMap":279},[283,284,286],"span",{"class":160,"line":285},1,[283,287,289],{"class":288},"sjfSM","\u002F\u002F Profiler says: \"Props changed: (filters)\". The filters object is recreated each render.\n",[283,291,293,297,301],{"class":160,"line":292},2,[283,294,296],{"class":295},"sPARh","function",[283,298,300],{"class":299},"smZ65"," Page",[283,302,304],{"class":303},"saISM","() {\n",[283,306,308,311,314,318,321,324,327,330,333,336,340],{"class":160,"line":307},3,[283,309,310],{"class":295},"  const",[283,312,313],{"class":303}," [",[283,315,317],{"class":316},"sPXB4","sort",[283,319,320],{"class":303},", ",[283,322,323],{"class":316},"setSort",[283,325,326],{"class":303},"] ",[283,328,329],{"class":295},"=",[283,331,332],{"class":299}," useState",[283,334,335],{"class":303},"(",[283,337,339],{"class":338},"sZ8jY","'price'",[283,341,342],{"class":303},");\n",[283,344,346,348,351,354,357,360,363,366,369,372,375,378],{"class":160,"line":345},4,[283,347,310],{"class":295},[283,349,350],{"class":316}," filters",[283,352,353],{"class":295}," =",[283,355,356],{"class":299}," useMemo",[283,358,359],{"class":303},"(() ",[283,361,362],{"class":295},"=>",[283,364,365],{"class":303}," ({ inStock: ",[283,367,368],{"class":316},"true",[283,370,371],{"class":303},", category: ",[283,373,374],{"class":338},"'shoes'",[283,376,377],{"class":303}," }), []);  ",[283,379,380],{"class":288},"\u002F\u002F stable identity\n",[283,382,384,387,390,394,396,399,402,405,408,410,412,414],{"class":160,"line":383},5,[283,385,386],{"class":295},"  return",[283,388,389],{"class":303}," \u003C",[283,391,393],{"class":392},"sZBmE","ProductList",[283,395,350],{"class":316},[283,397,398],{"class":295},"={",[283,400,401],{"class":303},"filters",[283,403,404],{"class":295},"}",[283,406,407],{"class":316}," sort",[283,409,398],{"class":295},[283,411,317],{"class":303},[283,413,404],{"class":295},[283,415,416],{"class":303}," \u002F>;\n",[283,418,420],{"class":160,"line":419},6,[283,421,422],{"class":303},"}\n",[283,424,426],{"class":160,"line":425},7,[283,427,428],{"class":288},"\u002F\u002F trade-off: useMemo only helps if ProductList is memoized (React.memo) or uses\n",[283,430,432],{"class":160,"line":431},8,[283,433,434],{"class":288},"\u002F\u002F filters in an effect dependency; otherwise it adds overhead for nothing.\n",[252,436,438],{"id":437},"_4-fix-and-compare","4. Fix and compare",[15,440,441],{},"Apply a fix (colocate state, memoize a component, stabilise a prop, split context), record the same interaction again, and compare commit duration and the number of rendered components.",[15,443,444],{},[35,445,42,448,42,451,42,454,42,456,42,459,42,461,42,466,42,473,42,477,42,481,42,484,42,488,42,492,42,496,42,498,42,501,42,503,42,506,42,509,42,513,42,515,42,518,42,520,42,523,42,526,42,530,42,532,42,535,42,537,42,540,42,543,42,547,42,549,42,552,42,554,42,557,42,560,42,564,42,566,42,569,42,571,42],{"viewBox":446,"width":38,"role":39,"ariaLabel":447,"style":41},"0 0 760 258","Reasons shown by the React Profiler for a component render and the usual fix for each.",[44,449],{"className":450,"x":48,"y":48,"width":38,"height":38,"fill":49},[47],[51,452,453],{},"Profiler render reasons and typical fixes",[55,455,447],{},[44,457],{"x":77,"y":77,"width":78,"height":458,"rx":80,"fill":81,"stroke":73,"style":82},"256",[84,460,453],{"x":86,"y":87,"fill":73,"style":88},[44,462],{"x":86,"y":91,"width":463,"height":464,"rx":48,"fill":73,"stroke":73,"style":465},"203.8","30.0","fill-opacity:0.06;stroke-opacity:0.4",[84,467,472],{"x":468,"y":469,"fill":73,"style":470,"textAnchor":471},"38.0","75.5","font-size:12.5px;font-weight:700","start","Reason shown",[44,474],{"x":475,"y":91,"width":476,"height":464,"rx":48,"fill":73,"stroke":73,"style":465},"231.8","250.1",[84,478,480],{"x":479,"y":469,"fill":73,"style":470,"textAnchor":102},"356.8","Likely cause",[44,482],{"x":483,"y":91,"width":476,"height":464,"rx":48,"fill":73,"stroke":73,"style":465},"481.9",[84,485,487],{"x":486,"y":469,"fill":73,"style":470,"textAnchor":102},"606.9","Typical fix",[44,489],{"x":86,"y":490,"width":463,"height":464,"rx":48,"fill":81,"stroke":73,"style":491},"86.0","stroke-opacity:0.35",[84,493,495],{"x":468,"y":494,"fill":73,"style":470,"textAnchor":471},"105.5","The parent component rendered",[44,497],{"x":475,"y":490,"width":476,"height":464,"rx":48,"fill":81,"stroke":73,"style":491},[84,499,500],{"x":479,"y":494,"fill":73,"style":107,"textAnchor":102},"unmemoized child",[44,502],{"x":483,"y":490,"width":476,"height":464,"rx":48,"fill":81,"stroke":73,"style":491},[84,504,505],{"x":486,"y":494,"fill":73,"style":107,"textAnchor":102},"React.memo or move state down",[44,507],{"x":86,"y":508,"width":463,"height":464,"rx":48,"fill":81,"stroke":73,"style":491},"116.0",[84,510,512],{"x":468,"y":511,"fill":73,"style":470,"textAnchor":471},"135.5","Props changed (callback)",[44,514],{"x":475,"y":508,"width":476,"height":464,"rx":48,"fill":81,"stroke":73,"style":491},[84,516,517],{"x":479,"y":511,"fill":73,"style":107,"textAnchor":102},"new function each render",[44,519],{"x":483,"y":508,"width":476,"height":464,"rx":48,"fill":81,"stroke":73,"style":491},[84,521,522],{"x":486,"y":511,"fill":73,"style":107,"textAnchor":102},"useCallback or compiler",[44,524],{"x":86,"y":525,"width":463,"height":464,"rx":48,"fill":81,"stroke":73,"style":491},"146.0",[84,527,529],{"x":468,"y":528,"fill":73,"style":470,"textAnchor":471},"165.5","Props changed (object)",[44,531],{"x":475,"y":525,"width":476,"height":464,"rx":48,"fill":81,"stroke":73,"style":491},[84,533,534],{"x":479,"y":528,"fill":73,"style":107,"textAnchor":102},"new object each render",[44,536],{"x":483,"y":525,"width":476,"height":464,"rx":48,"fill":81,"stroke":73,"style":491},[84,538,539],{"x":486,"y":528,"fill":73,"style":107,"textAnchor":102},"useMemo or hoist constant",[44,541],{"x":86,"y":542,"width":463,"height":464,"rx":48,"fill":81,"stroke":73,"style":491},"176.0",[84,544,546],{"x":468,"y":545,"fill":73,"style":470,"textAnchor":471},"195.5","Context changed",[44,548],{"x":475,"y":542,"width":476,"height":464,"rx":48,"fill":81,"stroke":73,"style":491},[84,550,551],{"x":479,"y":545,"fill":73,"style":107,"textAnchor":102},"broad context value",[44,553],{"x":483,"y":542,"width":476,"height":464,"rx":48,"fill":81,"stroke":73,"style":491},[84,555,556],{"x":486,"y":545,"fill":73,"style":107,"textAnchor":102},"split context or selector",[44,558],{"x":86,"y":559,"width":463,"height":464,"rx":48,"fill":81,"stroke":73,"style":491},"206.0",[84,561,563],{"x":468,"y":562,"fill":73,"style":470,"textAnchor":471},"225.5","Hook changed",[44,565],{"x":475,"y":559,"width":476,"height":464,"rx":48,"fill":81,"stroke":73,"style":491},[84,567,568],{"x":479,"y":562,"fill":73,"style":107,"textAnchor":102},"state update in this component",[44,570],{"x":483,"y":559,"width":476,"height":464,"rx":48,"fill":81,"stroke":73,"style":491},[84,572,573],{"x":486,"y":562,"fill":73,"style":107,"textAnchor":102},"expected; check frequency",[181,575,577],{"id":576},"verification","Verification",[15,579,580],{},"The same interaction should show fewer components rendered (more grey in the flame chart) and a shorter commit duration. Verify the total interaction time in the browser Performance panel with CPU throttling, since React's commit is only part of the work. In the field, check INP for the interaction target.",[181,582,584],{"id":583},"worked-example-a-booking-calendar","Worked Example: A Booking Calendar",[15,586,587,588,591,592,595,596,599,600,602,603,606],{},"A booking app's calendar re-rendered slowly when a user hovered over time slots. The Profiler showed each hover committed 1,400 components in 90ms. \"Why did this render?\" showed that every ",[215,589,590],{},"TimeSlot"," re-rendered because \"The parent component rendered\" — the calendar stored ",[215,593,594],{},"hoveredSlot"," in its own state. The team moved hover styling to CSS (",[215,597,598],{},":hover",") for visual feedback and kept only the selected slot in state, passed to ",[215,601,590],{}," as a boolean ",[215,604,605],{},"isSelected"," prop on a memoized component. Hovering no longer committed at all; selecting a slot committed 2 components in 1ms. INP for slot selection fell from 210ms to 60ms.",[181,608,610],{"id":609},"using-the-profiler-on-production-builds","Using the Profiler on Production Builds",[15,612,613,614,617,618,620,621,624],{},"Development builds include extra checks that slow rendering and Strict Mode double-invokes renders, so timings are inflated. For realistic numbers, build with the profiling-enabled React DOM (aliasing ",[215,615,616],{},"react-dom$"," to ",[215,619,217],{}," in the bundler), which keeps production optimizations while enabling the Profiler. Many teams keep a profiling build available in staging for this purpose. The ",[215,622,623],{},"\u003CProfiler>"," component can also log render timings programmatically for specific subtrees, which is useful for automated performance tests.",[274,626,628],{"className":276,"code":627,"language":278,"meta":279,"style":279},"import { Profiler } from 'react';\nfunction onRender(id, phase, actualDuration) {\n  if (actualDuration > 16) console.warn(`[${id}] ${phase} took ${actualDuration.toFixed(1)}ms`);\n}\n\u003CProfiler id=\"ProductGrid\" onRender={onRender}>\u003CProductGrid \u002F>\u003C\u002FProfiler>\n\u002F\u002F trade-off: Profiler timings are only collected in development and profiling\n\u002F\u002F builds; in normal production builds onRender is not called.\n",[215,629,630,647,673,728,732,771,776],{"__ignoreMap":279},[283,631,632,635,638,641,644],{"class":160,"line":285},[283,633,634],{"class":295},"import",[283,636,637],{"class":303}," { Profiler } ",[283,639,640],{"class":295},"from",[283,642,643],{"class":338}," 'react'",[283,645,646],{"class":303},";\n",[283,648,649,651,654,656,660,662,665,667,670],{"class":160,"line":292},[283,650,296],{"class":295},[283,652,653],{"class":299}," onRender",[283,655,335],{"class":303},[283,657,659],{"class":658},"sQw3B","id",[283,661,320],{"class":303},[283,663,664],{"class":658},"phase",[283,666,320],{"class":303},[283,668,669],{"class":658},"actualDuration",[283,671,672],{"class":303},") {\n",[283,674,675,678,681,684,687,690,693,695,698,700,703,705,708,710,713,716,718,720,723,726],{"class":160,"line":307},[283,676,677],{"class":295},"  if",[283,679,680],{"class":303}," (actualDuration ",[283,682,683],{"class":295},">",[283,685,686],{"class":316}," 16",[283,688,689],{"class":303},") console.",[283,691,692],{"class":299},"warn",[283,694,335],{"class":303},[283,696,697],{"class":338},"`[${",[283,699,659],{"class":303},[283,701,702],{"class":338},"}] ${",[283,704,664],{"class":303},[283,706,707],{"class":338},"} took ${",[283,709,669],{"class":303},[283,711,712],{"class":338},".",[283,714,715],{"class":299},"toFixed",[283,717,335],{"class":338},[283,719,77],{"class":316},[283,721,722],{"class":338},")",[283,724,725],{"class":338},"}ms`",[283,727,342],{"class":303},[283,729,730],{"class":160,"line":345},[283,731,422],{"class":303},[283,733,734,737,740,743,745,748,750,752,755,757,760,763,766,768],{"class":160,"line":383},[283,735,736],{"class":303},"\u003C",[283,738,739],{"class":392},"Profiler",[283,741,742],{"class":316}," id",[283,744,329],{"class":295},[283,746,747],{"class":338},"\"ProductGrid\"",[283,749,653],{"class":316},[283,751,398],{"class":295},[283,753,754],{"class":303},"onRender",[283,756,404],{"class":295},[283,758,759],{"class":303},">\u003C",[283,761,762],{"class":392},"ProductGrid",[283,764,765],{"class":303}," \u002F>\u003C\u002F",[283,767,739],{"class":392},[283,769,770],{"class":303},">\n",[283,772,773],{"class":160,"line":419},[283,774,775],{"class":288},"\u002F\u002F trade-off: Profiler timings are only collected in development and profiling\n",[283,777,778],{"class":160,"line":425},[283,779,780],{"class":288},"\u002F\u002F builds; in normal production builds onRender is not called.\n",[15,782,783],{},[35,784,42,787,42,790,42,793,42,795,42,798,42,800,42,807,42,814,42,819,42,823,42,828,42],{"viewBox":785,"width":38,"role":39,"ariaLabel":786,"style":41},"0 0 760 132","Bar chart of how many components rendered per hover interaction before and after fixing a wasted render source.",[44,788],{"className":789,"x":48,"y":48,"width":38,"height":38,"fill":49},[47],[51,791,792],{},"Components rendered per hover in a booking calendar",[55,794,786],{},[44,796],{"x":77,"y":77,"width":78,"height":797,"rx":80,"fill":81,"stroke":73,"style":82},"130",[84,799,792],{"x":86,"y":87,"fill":73,"style":88},[84,801,806],{"x":802,"y":803,"fill":73,"style":804,"textAnchor":805},"215.6","70.0","font-size:13px","end","Hover state in calendar",[44,808],{"x":809,"y":91,"width":810,"height":811,"rx":812,"fill":81,"stroke":73,"style":813},"227.6","440.4","19","3","fill-opacity:0.7;stroke-opacity:0.35",[84,815,818],{"x":816,"y":803,"fill":73,"style":817},"674.0","font-size:12px;font-weight:600","1400",[84,820,822],{"x":802,"y":821,"fill":73,"style":804,"textAnchor":805},"101.0","CSS hover + memoized slots",[44,824],{"x":809,"y":825,"width":826,"height":811,"rx":812,"fill":136,"stroke":137,"style":827},"87.0","2.0","fill-opacity:0.7;stroke-opacity:0.9",[84,829,48],{"x":830,"y":821,"fill":73,"style":817},"235.6",[181,832,834],{"id":833},"reading-the-timeline-for-long-sessions","Reading the Timeline for Long Sessions",[15,836,837],{},"For interactions that involve several commits — a drag, a multi-step form, typing a word — the Profiler's commit selector at the top shows a bar per commit, with height proportional to duration. Tall bars indicate the expensive commits to inspect first. Clicking through commits while watching which components render reveals patterns such as a component that renders on every commit even though its output only changes once. Use the filter setting to hide commits below a threshold (for example 2ms) so only meaningful ones remain.",[181,839,841],{"id":840},"common-mistakes","Common Mistakes",[186,843,844,850,856,862],{},[189,845,846,849],{},[192,847,848],{},"Profiling long sessions."," Too many commits to interpret.",[189,851,852,855],{},[192,853,854],{},"Trusting development timings."," Use profiling builds for absolute numbers.",[189,857,858,861],{},[192,859,860],{},"Fixing the fastest components."," Start with the ranked chart's top entries.",[189,863,864,867],{},[192,865,866],{},"Ignoring browser work."," Commit time excludes style, layout and paint.",[181,869,871],{"id":870},"edge-cases","Edge Cases",[15,873,874,877],{},[192,875,876],{},"Server Components."," Only client components appear in the Profiler; server work is not shown.",[15,879,880,883],{},[192,881,882],{},"Concurrent renders."," Interrupted renders may appear differently; focus on committed work.",[15,885,886,889],{},[192,887,888],{},"Third-party components."," Libraries may re-render internally; check their memoization options.",[15,891,892,895,896,899],{},[192,893,894],{},"Effects."," Expensive ",[215,897,898],{},"useEffect"," work runs after commit and does not appear as render time; use the Performance panel to see it.",[181,901,903],{"id":902},"faq","FAQ",[905,906,909,913],"details",{"className":907},[908],"faq-item",[910,911,912],"summary",{},"How do I see why a component re-rendered?",[15,914,915],{},"Enable \"Record why each component rendered while profiling\" in Profiler settings, record, then select a component to see the reason.",[905,917,919,922],{"className":918},[908],[910,920,921],{},"What do grey components in the flame chart mean?",[15,923,924],{},"They did not render in that commit, which is what you want for unaffected parts of the tree.",[905,926,928,931],{"className":927},[908],[910,929,930],{},"Can I profile a production site?",[15,932,933],{},"Only with a profiling build of React. Standard production builds do not expose Profiler data.",[905,935,937,940],{"className":936},[908],[910,938,939],{},"What is a commit?",[15,941,942],{},"The phase where React applies changes to the DOM after rendering. Each state update batch results in one commit.",[905,944,946,949],{"className":945},[908],[910,947,948],{},"Is a wasted render always a problem?",[15,950,951],{},"No. Cheap wasted renders are harmless. They matter when they are frequent, numerous or expensive.",[905,953,955,958],{"className":954},[908],[910,956,957],{},"Does highlighting updates help?",[15,959,960],{},"It gives a quick visual sense of what re-renders on each interaction, useful for spotting broad re-renders before profiling in detail.",[905,962,964,967],{"className":963},[908],[910,965,966],{},"How does the Profiler relate to INP?",[15,968,969],{},"Render and commit time are part of an interaction's processing and presentation time. INP also includes the browser's style, layout and paint, which the Performance panel shows.",[905,971,973,976],{"className":972},[908],[910,974,975],{},"Can I automate render checks in tests?",[15,977,978,979,981,982,984],{},"Yes. The ",[215,980,623],{}," component's ",[215,983,754],{}," callback, used in a profiling build, can assert that key interactions stay under a render-time budget.",[905,986,988,991],{"className":987},[908],[910,989,990],{},"Why do some components render twice in development?",[15,992,993],{},"Strict Mode intentionally double-invokes renders in development to surface side effects. It does not happen in production builds.",[905,995,997,1000],{"className":996},[908],[910,998,999],{},"Does the Profiler slow the app down?",[15,1001,1002],{},"Slightly, while recording. Compare runs under the same conditions rather than reading absolute timings too literally.",[181,1004,1006],{"id":1005},"related","Related",[186,1008,1009,1016,1023],{},[189,1010,1011,1015],{},[19,1012,1014],{"href":1013},"\u002Fframework-performance\u002Freact-rendering-performance\u002Fwhen-usememo-and-usecallback-actually-help\u002F","When useMemo and useCallback actually help"," — stabilising props.",[189,1017,1018,1022],{},[19,1019,1021],{"href":1020},"\u002Fframework-performance\u002Freact-rendering-performance\u002Fstopping-context-re-render-cascades\u002F","Stopping context re-render cascades"," — context-caused renders.",[189,1024,1025,1029],{},[19,1026,1028],{"href":1027},"\u002Fcore-web-vitals-measurement\u002Fprofiling-event-handlers-for-inp\u002F","Profiling event handlers for INP"," — browser-side profiling.",[1031,1032,1034],"script",{"type":1033},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"How to Find Wasted Renders with the React Profiler\",\n  \"description\": \"A step-by-step workflow for using the React Profiler to find unnecessary and expensive renders behind slow interactions.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Record one interaction at a time\",\n      \"text\": \"Start recording, perform a single interaction (type one character, click one filter), stop.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Read the flame and ranked charts\",\n      \"text\": \"The flame chart shows the tree for a commit: wide, yellow components took longest; grey components did not render.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Check why each component rendered\",\n      \"text\": \"Select a component: the right panel lists \\\"Why did this render?\\\" — for example \\\"Props changed: (onSelect)\\\", \\\"Context changed\\\", or \\\"The parent component rendered\\\".\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Fix and compare\",\n      \"text\": \"Apply a fix (colocate state, memoize a component, stabilise a prop, split context), record the same interaction again, and compare commit duration and the number of rendered components.\"\n    }\n  ]\n}\n",[1031,1036,1037],{"type":1033},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"How to Find Wasted Renders with the React Profiler\",\n  \"description\": \"A step-by-step workflow for using the React Profiler to find unnecessary and expensive renders behind slow interactions.\",\n  \"datePublished\": \"2026-10-06\",\n  \"dateModified\": \"2026-10-06\",\n  \"author\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"publisher\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"mainEntityOfPage\": {\n    \"@type\": \"WebPage\",\n    \"@id\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002Freact-rendering-performance\u002Ffinding-wasted-renders-with-the-react-profiler\u002F\"\n  }\n}\n",[1031,1039,1040],{"type":1033},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"BreadcrumbList\",\n  \"itemListElement\": [\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 1,\n      \"name\": \"Home\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 2,\n      \"name\": \"Framework Performance\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 3,\n      \"name\": \"React Rendering Performance\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002Freact-rendering-performance\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"Finding Wasted Renders with the React Profiler\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002Freact-rendering-performance\u002Ffinding-wasted-renders-with-the-react-profiler\u002F\"\n    }\n  ]\n}\n",[1042,1043,1044],"style",{},"html pre.shiki code .sjfSM, html code.shiki .sjfSM{--shiki-default:#66707B;--shiki-dark:#BDC4CC;--shiki-light:#66707B}html pre.shiki code .sPARh, html code.shiki .sPARh{--shiki-default:#A0111F;--shiki-dark:#FF9492;--shiki-light:#A0111F}html pre.shiki code .smZ65, html code.shiki .smZ65{--shiki-default:#622CBC;--shiki-dark:#DBB7FF;--shiki-light:#622CBC}html pre.shiki code .saISM, html code.shiki .saISM{--shiki-default:#0E1116;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}html pre.shiki code .sZ8jY, html code.shiki .sZ8jY{--shiki-default:#032563;--shiki-dark:#ADDCFF;--shiki-light:#032563}html pre.shiki code .sZBmE, html code.shiki .sZBmE{--shiki-default:#024C1A;--shiki-dark:#72F088;--shiki-light:#024C1A}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 .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html pre.shiki code .sQw3B, html code.shiki .sQw3B{--shiki-default:#702C00;--shiki-dark:#FFB757;--shiki-light:#702C00}",{"title":279,"searchDepth":292,"depth":292,"links":1046},[1047,1048,1049,1055,1056,1057,1058,1059,1060,1061,1062],{"id":183,"depth":292,"text":184},{"id":221,"depth":292,"text":222},{"id":249,"depth":292,"text":250,"children":1050},[1051,1052,1053,1054],{"id":254,"depth":307,"text":255},{"id":261,"depth":307,"text":262},{"id":268,"depth":307,"text":269},{"id":437,"depth":307,"text":438},{"id":576,"depth":292,"text":577},{"id":583,"depth":292,"text":584},{"id":609,"depth":292,"text":610},{"id":833,"depth":292,"text":834},{"id":840,"depth":292,"text":841},{"id":870,"depth":292,"text":871},{"id":902,"depth":292,"text":903},{"id":1005,"depth":292,"text":1006},"A step-by-step workflow for using the React Profiler to find unnecessary and expensive renders behind slow interactions.","md",{"slug":1066,"type":1067,"breadcrumb":1068,"datePublished":1076,"dateModified":1076},"finding-wasted-renders-with-the-react-profiler","article",[1069,1072,1073,1074],{"name":1070,"url":1071},"Home","\u002F",{"name":27,"url":26},{"name":22,"url":21},{"name":5,"url":1075},"\u002Fframework-performance\u002Freact-rendering-performance\u002Ffinding-wasted-renders-with-the-react-profiler\u002F","2026-10-06",true,"\u002Fframework-performance\u002Freact-rendering-performance\u002Ffinding-wasted-renders-with-the-react-profiler",{"title":1080,"description":1081},"Finding Wasted Renders with the React DevTools Profiler","Use the React DevTools Profiler to record interactions, read flame and ranked charts, see why each component rendered, and fix the renders that slow INP.","framework-performance\u002Freact-rendering-performance\u002Ffinding-wasted-renders-with-the-react-profiler\u002Findex","xgaHKIA11wFTLnZ9X4IwOQyc38g37PSAjv5LURCjZO8",[1085,1089],{"title":1086,"path":1087,"stem":1088,"children":-1},"Adopting the React Compiler","\u002Fframework-performance\u002Freact-rendering-performance\u002Fadopting-the-react-compiler","framework-performance\u002Freact-rendering-performance\u002Fadopting-the-react-compiler\u002Findex",{"title":1090,"path":1091,"stem":1092,"children":-1},"Stopping Context Re-Render Cascades","\u002Fframework-performance\u002Freact-rendering-performance\u002Fstopping-context-re-render-cascades","framework-performance\u002Freact-rendering-performance\u002Fstopping-context-re-render-cascades\u002Findex",1791308072411]