Optimize provider update sidebar pill renders#3915
Conversation
Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
Co-authored-by: Julius Marminge <juliusmarminge@users.noreply.github.com>
| useEffect(() => { | ||
| if (!dismissAfterVisibleMs || !viewKey) { | ||
| if (!displayedView || !dismissAfterVisibleMs || !viewKey) { | ||
| return; | ||
| } | ||
| if (exitingKey === viewKey) { | ||
| return; | ||
| } | ||
| const timeoutId = window.setTimeout(() => { | ||
| startExit(viewKey, null, viewKey); | ||
| startExit(displayedView, viewKey); | ||
| }, dismissAfterVisibleMs); | ||
|
|
||
| return () => window.clearTimeout(timeoutId); | ||
| }, [dismissAfterVisibleMs, exitingKey, startExit, viewKey]); | ||
| }, [dismissAfterVisibleMs, displayedView, exitingKey, startExit, viewKey]); |
There was a problem hiding this comment.
🟡 Medium sidebar/SidebarProviderUpdatePill.tsx:63
The auto-dismiss timeout resets on every rerender because useProviderUpdatePillAutoDismiss now depends on the displayedView object reference, and getProviderUpdateSidebarPillView returns a fresh object each render even when the view key is unchanged. Any unrelated rerender during the dismiss window clears and restarts the timer. With repeated rerenders the success notification can stay visible indefinitely instead of dismissing after dismissAfterVisibleMs. The previous implementation relied on a stored renderedView that remained referentially stable for an unchanged key. Consider keying the effect on viewKey (and dismissAfterVisibleMs) rather than the whole view object, or memoizing the view by key so the reference stays stable.
useEffect(() => {
if (!displayedView || !dismissAfterVisibleMs || !viewKey) {
return;
}
if (exitingKey === viewKey) {
return;
}
- const displayedViewRef = displayedView;
const timeoutId = window.setTimeout(() => {
- startExit(displayedView, viewKey);
+ startExit(displayedViewRef, viewKey);
}, dismissAfterVisibleMs);
return () => window.clearTimeout(timeoutId);
- }, [dismissAfterVisibleMs, displayedView, exitingKey, startExit, viewKey]);
+ }, [dismissAfterVisibleMs, viewKey, exitingKey, startExit]);🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/web/src/components/sidebar/SidebarProviderUpdatePill.tsx around lines 63-75:
The auto-dismiss timeout resets on every rerender because `useProviderUpdatePillAutoDismiss` now depends on the `displayedView` object reference, and `getProviderUpdateSidebarPillView` returns a fresh object each render even when the view `key` is unchanged. Any unrelated rerender during the dismiss window clears and restarts the timer. With repeated rerenders the success notification can stay visible indefinitely instead of dismissing after `dismissAfterVisibleMs`. The previous implementation relied on a stored `renderedView` that remained referentially stable for an unchanged key. Consider keying the effect on `viewKey` (and `dismissAfterVisibleMs`) rather than the whole view object, or memoizing the view by key so the reference stays stable.
What Changed
SidebarProviderUpdatePillso the visible pill view is derived during render instead of synchronized throughuseEffectstate.SidebarProviderUpdatePillContentso the content owns its dismissal/exit state and can lazily capture the first provider check threshold on mount.useProviderUpdatePillAutoDismisshook.Why
react-doctorflagged this component for state that was only used by handlers and synchronoussetStateinside effects, both of which caused extra commits. The React “You Might Not Need an Effect” guidance recommends calculating derived values during render instead of storing them via effects.Post-fix
react-doctorno longer listsSidebarProviderUpdatePillunder those two findings.UI Changes
React Scan recordings captured with React Scan enabled:
react_scan_provider_pill_before.mp4— five remounts increased the Profiler counter from 4 to 12.react_scan_provider_pill_after.mp4— the same five remounts increased the counter from 3 to 7.Checklist
Validation:
react-doctor@0.7.4 . --verbose --category performance --no-telemetry(post-fix scan still reports unrelated repo-wide findings, but no longer reportsSidebarProviderUpdatePillfor the fixed categories)vp checkvp run typecheckNote
Refactor
SidebarProviderUpdatePillto fix visible-after timestamp and simplify state modelSidebarProviderUpdatePillContentcomponent, makingSidebarProviderUpdatePilla thin wrapper that short-circuits when there are no providers.renderedView,pendingView,exitingKey, syncing effect) with a simplerexitStateobject and adismissedKeysset.visibleAfterIsoto be initialized once at mount fromlatestProviderCheckedAt(providers)and never re-synchronized, so the set of visible updates stays stable after mount.📊 Macroscope summarized bd0cd27. 1 file reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted
🗂️ Filtered Issues
No issues evaluated.