-
Notifications
You must be signed in to change notification settings - Fork 28.8k
wip #81404
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: canary
Are you sure you want to change the base?
wip #81404
Conversation
5783f57
to
d744857
Compare
isBuildError={isBuildError} | ||
scale={state.scale} | ||
/> | ||
<NextLogo ref={triggerRef} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The NextLogo
component is not a forwardRef component but is being passed a ref={triggerRef}
prop, which will cause the ref to not be attached to the actual button element.
📄 Review details
🔍 Technical Analysis
The NextLogo
component on line 67 is receiving a ref={triggerRef}
prop, but NextLogo
is defined as a regular function component that accepts React.ComponentProps<'button'>
, not a forwardRef component. This means the ref will not be forwarded to the actual button element inside NextLogo
.
Looking at the NextLogo
component implementation, it has its own internal triggerRef
at line 40, but this is completely separate from the ref being passed from the parent component. The triggerRef
from PanelContext
is intended to be used for click-outside detection in useClickOutside(menuRef, triggerRef, closeOnClickOutside, ...)
(see dev-overlay-menu.tsx line 45), but it will never be properly attached to the DOM element.
This will break functionality like:
- Click-outside detection for closing menus
- Focus management for accessibility
- Any other features that depend on having a reference to the trigger button
The bug manifests because there are two separate triggerRef
references:
- One created in
dev-overlay.tsx
line 62 and passed throughPanelContext
- Another created internally in
NextLogo
component line 40 that actually gets attached to the button
Only the internal one gets attached to the DOM, while the external one remains null
, breaking dependent functionality.
🔧 Suggested Fix
Convert NextLogo
to a forwardRef component to properly forward the ref to the button element:
export const NextLogo = React.forwardRef<HTMLButtonElement, React.ComponentProps<'button'>>(
function NextLogo(buttonProps, forwardedRef) {
// ... existing code ...
// Remove the internal triggerRef and use forwardedRef instead:
// const triggerRef = useRef<HTMLButtonElement | null>(null) // Remove this line
// In the button JSX, use forwardedRef:
<button
id="next-logo"
ref={forwardedRef} // Use forwardedRef instead of triggerRef
// ... rest of props
>
This will ensure the ref from PanelContext
is properly forwarded to the actual button element.
👍 or 👎 to improve Vade.
const width = measuredWidth === 0 ? 'auto' : measuredWidth | ||
|
||
useEffect(() => { | ||
setIsErrorExpanded(hasError) | ||
}, [hasError]) | ||
console.log('its time for next logo',state.disableDevIndicator); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Development console.log statement was left in the code that will pollute the console in production builds.
📄 Review details
🔍 Technical Analysis
A console.log('its time for next logo',state.disableDevIndicator);
statement was left in the production code. This is a development debugging statement that should not be present in the final codebase as it will:
- Pollute the browser console for end users
- Create unnecessary logging noise in production environments
- Potentially expose internal state information
- Impact performance slightly due to unnecessary console operations
This appears to be a debugging statement that was accidentally committed along with the refactoring changes.
🔧 Suggested Fix
Remove the console.log statement:
// Remove this line:
console.log('its time for next logo',state.disableDevIndicator);
If logging is needed for debugging purposes, consider using a proper debug utility that can be conditionally enabled in development environments only, or use proper debugging tools instead of console.log statements in production code.
👍 or 👎 to improve Vade.
|
||
const triggerRef = useRef<HTMLButtonElement>(null) | ||
// @ts-expect-error | ||
process.env.__NEXT_DEVTOOL_NEW_PANEL_UI = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Direct runtime assignment to process.env.__NEXT_DEVTOOL_NEW_PANEL_UI = true
mutates the process environment at runtime, which can cause issues in different deployment environments.
📄 Review details
🔍 Technical Analysis
The code directly assigns process.env.__NEXT_DEVTOOL_NEW_PANEL_UI = true
at runtime inside a React component. This is problematic because:
-
Process.env mutation:
process.env
is typically meant to be read-only after application startup. Mutating it at runtime can cause unpredictable behavior, especially in environments whereprocess.env
might be frozen or where multiple instances share the same process. -
Side effects in render: This assignment happens every time the component renders, which is a side effect that should not occur during rendering.
-
Environment inconsistency: The value is being set conditionally based on runtime logic rather than build-time configuration, which can lead to inconsistent behavior across different environments or instances.
-
TypeScript suppression: The
@ts-expect-error
comment indicates that TypeScript knows this is incorrect, but the error is being suppressed rather than fixed properly.
The assignment appears to be forcing the new panel UI to be enabled, but this should be determined at build time or through proper configuration, not through runtime mutation of process.env
.
🔧 Suggested Fix
Remove the runtime process.env
mutation and handle this through proper configuration:
- Remove the problematic line:
// Remove these lines:
// @ts-expect-error
process.env.__NEXT_DEVTOOL_NEW_PANEL_UI = true
- Use a proper constant or configuration:
// Add at the top of the file or in a config file:
const ENABLE_NEW_PANEL_UI = true // or read from proper config
// Then use this constant instead of process.env in the conditional:
scale={ENABLE_NEW_PANEL_UI ? state.scale : scale}
- If you need runtime control, use component state or context:
const [useNewPanelUI] = useState(true)
// or get from a configuration context
This ensures consistent behavior and avoids mutating the global process environment.
👍 or 👎 to improve Vade.
d744857
to
a358d2a
Compare
return ( | ||
<DevToolsInfo | ||
title={`${routeType} Route`} | ||
learnMoreLink={learnMore} | ||
close={close} | ||
isOpen={isOpen} | ||
triggerRef={{ current: null }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The RouteInfo component passes a hardcoded null ref object that will break focus management functionality.
📄 Review details
🔍 Technical Analysis
In the RouteInfo component, line 141 passes triggerRef={{ current: null }}
to the DevToolsInfo component. This creates a static object with a null current property that never gets updated.
The DevToolsInfo component uses this triggerRef in useFocusTrap and useClickOutside hooks, which expect a proper React ref that can hold references to DOM elements. The useFocusTrap hook specifically calls triggerRef.current?.focus()
to restore focus when the overlay closes, but this will never work because current
is always null.
This will break keyboard navigation and focus management in the dev tools overlay, potentially making it inaccessible to keyboard users and breaking the expected UX flow when the overlay is dismissed.
🔧 Suggested Fix
Replace the hardcoded null ref with a proper useRef hook:
export function RouteInfo({ isOpen, close, ...props }: { isOpen: boolean; close: () => void } & HTMLProps<HTMLDivElement>) {
const { state } = useDevOverlayContext()
const triggerRef = useRef<HTMLButtonElement>(null) // Add this line
const routeType = state.staticIndicator ? 'Static' : 'Dynamic'
const learnMore = state.staticIndicator
? learnMoreLink[state.routerType].static
: learnMoreLink[state.routerType].dynamic
return (
<DevToolsInfo
title={`${routeType} Route`}
learnMoreLink={learnMore}
close={close}
isOpen={isOpen}
triggerRef={triggerRef} // Use the ref instead of { current: null }
{...props}
>
<RouteInfoBody />
</DevToolsInfo>
)
}
Don't forget to import useRef from React.
👍 or 👎 to improve Vade.
Todos: