-
Notifications
You must be signed in to change notification settings - Fork 0
Fix: useSidebar hook throws during SSR/prerendering #236
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
Fix: useSidebar hook throws during SSR/prerendering #236
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…bility Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
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.
Pull request overview
This PR fixes a Next.js build failure during static site generation where the header-bar component's SidebarTrigger calls useSidebar() without a SidebarProvider in the tree, causing a hard error. The solution modifies useSidebar() to return safe default values instead of throwing when the provider is missing.
Changes:
- Modified
useSidebar()hook to returnDEFAULT_SIDEBAR_STATEwhen no provider exists, enabling graceful degradation during SSR/prerendering - Extracted
DEFAULT_SIDEBAR_STATEconstant with no-op functions for all sidebar operations
Comments suppressed due to low confidence (2)
packages/components/src/ui/sidebar.tsx:74
- Silently returning default values when the provider is missing hides configuration errors from developers. This approach differs from the established pattern in the codebase where other context hooks (useCarousel, useChart, useFormField, useSchemaContext) throw errors when used outside their providers.
Consider adding a development-time warning to help developers identify misconfigurations:
function useSidebar() {
const context = React.useContext(SidebarContext)
if (!context) {
if (process.env.NODE_ENV !== 'production') {
console.warn(
'useSidebar: No SidebarProvider found. Using default values. ' +
'This may indicate a missing SidebarProvider in your component tree.'
)
}
return DEFAULT_SIDEBAR_STATE
}
return context
}This preserves SSR compatibility while alerting developers during development that they may be missing proper setup.
function useSidebar() {
const context = React.useContext(SidebarContext)
if (!context) {
// Return default values to allow components to gracefully degrade without breaking the build
return DEFAULT_SIDEBAR_STATE
}
return context
}
packages/components/src/ui/sidebar.tsx:74
- The approach taken here differs from the ToggleGroupContext pattern (lines 16-21 in toggle-group.tsx) which provides a default value directly in createContext, preventing null checks altogether. Consider applying the same pattern here:
const SidebarContext = React.createContext<SidebarContextProps>(DEFAULT_SIDEBAR_STATE)Then simplify useSidebar to:
function useSidebar() {
return React.useContext(SidebarContext)
}This approach:
- Eliminates the null check entirely
- Aligns with the ToggleGroupContext implementation pattern
- Still provides SSR compatibility
- Maintains graceful degradation
Note: You'd still want to add a dev warning (see other comment) to help developers identify when they're missing the provider.
const SidebarContext = React.createContext<SidebarContextProps | null>(null)
// Default sidebar state for when no provider exists (e.g., during SSR/prerendering)
const DEFAULT_SIDEBAR_STATE: SidebarContextProps = {
state: "expanded",
open: true,
setOpen: () => {},
openMobile: false,
setOpenMobile: () => {},
isMobile: false,
toggleSidebar: () => {},
}
function useSidebar() {
const context = React.useContext(SidebarContext)
if (!context) {
// Return default values to allow components to gracefully degrade without breaking the build
return DEFAULT_SIDEBAR_STATE
}
return context
}
| function useSidebar() { | ||
| const context = React.useContext(SidebarContext) | ||
| if (!context) { | ||
| throw new Error("useSidebar must be used within a SidebarProvider.") | ||
| // Return default values to allow components to gracefully degrade without breaking the build | ||
| return DEFAULT_SIDEBAR_STATE |
Copilot
AI
Jan 27, 2026
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 header-bar component (packages/components/src/renderers/navigation/header-bar.tsx:26) unconditionally renders a SidebarTrigger, but this creates an implicit coupling between header-bar and SidebarProvider. During SSR or when header-bar is used without a sidebar, the trigger renders but has no sidebar to control.
Consider one of these architectural improvements:
- Make the sidebar trigger optional in header-bar schema:
interface HeaderBarSchema {
showSidebarTrigger?: boolean; // Default: false for better SSR compatibility
// ... other props
}- Add a dedicated slot for the trigger so users explicitly choose when to include it:
interface HeaderBarSchema {
leftSlot?: SchemaNode[]; // Users can explicitly add SidebarTrigger here
// ... other props
}This would align with ObjectUI's principle of "JSON-driven composition" where components are explicitly configured rather than having implicit dependencies.
|
|
||
| const SidebarContext = React.createContext<SidebarContextProps | null>(null) | ||
|
|
||
| // Default sidebar state for when no provider exists (e.g., during SSR/prerendering) |
Copilot
AI
Jan 27, 2026
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 comment mentions "SSR/prerendering" but the actual issue is specifically about static site generation where components are rendered outside of a provider tree. Consider updating the comment to be more precise:
// Default sidebar state for graceful degradation when used outside SidebarProvider
// (e.g., during SSR, static generation, or standalone component usage)This clarifies that it's not just an SSR concern but a broader architectural pattern for components that may be rendered in isolation.
| // Default sidebar state for when no provider exists (e.g., during SSR/prerendering) | |
| // Default sidebar state for graceful degradation when used outside SidebarProvider | |
| // (e.g., during SSR, static generation, or standalone component usage) |
Next.js build fails when prerendering pages containing
header-barcomponent. TheSidebarTriggercallsuseSidebar()which throws when noSidebarProviderexists in the context tree.Changes
useSidebar()to return safe defaults instead of throwing when provider is missingDEFAULT_SIDEBAR_STATEconstant for consistencyImplementation
This allows components using sidebar hooks to render during static generation while maintaining full functionality when wrapped in a provider.
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
fonts.googleapis.com/usr/local/bin/node node /home/REDACTED/work/objectui/objectui/apps/site/node_modules/.bin/../next/dist/bin/next build(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.