File tree Expand file tree Collapse file tree 3 files changed +58
-2
lines changed
packages/docusaurus-theme-openapi-docs/src/theme
ApiExplorer/MethodEndpoint Expand file tree Collapse file tree 3 files changed +58
-2
lines changed Original file line number Diff line number Diff line change 88import React from "react" ;
99
1010import BrowserOnly from "@docusaurus/BrowserOnly" ;
11+ import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment" ;
1112import { useTypedSelector } from "@theme/ApiItem/hooks" ;
1213
1314function colorForMethod ( method : string ) {
@@ -38,6 +39,26 @@ export interface Props {
3839}
3940
4041function MethodEndpoint ( { method, path, context } : Props ) {
42+ // During SSR, render without Redux store access to avoid "Cannot read properties
43+ // of null (reading 'store')" errors caused by useSelector running outside a Provider.
44+ if ( ! ExecutionEnvironment . canUseDOM ) {
45+ return (
46+ < >
47+ < pre className = "openapi__method-endpoint" >
48+ < span className = { "badge badge--" + colorForMethod ( method ) } >
49+ { method === "event" ? "Webhook" : method . toUpperCase ( ) }
50+ </ span > { " " }
51+ { method !== "event" && (
52+ < h2 className = "openapi__method-endpoint-path" >
53+ { `${ path . replace ( / { ( [ a - z 0 - 9 - _ ] + ) } / gi, ":$1" ) } ` }
54+ </ h2 >
55+ ) }
56+ </ pre >
57+ < div className = "openapi__divider" />
58+ </ >
59+ ) ;
60+ }
61+
4162 let serverValue = useTypedSelector ( ( state : any ) => state . server . value ) ;
4263 let serverUrlWithVariables = "" ;
4364
Original file line number Diff line number Diff line change @@ -214,6 +214,14 @@ const AnyOneOf: React.FC<SchemaProps> = ({
214214 schemaPath,
215215} ) => {
216216 const key = schema . oneOf ? "oneOf" : "anyOf" ;
217+ const schemaArray = schema [ key ] ;
218+
219+ // Empty oneOf/anyOf arrays are valid in OpenAPI specs but would cause the
220+ // Tabs component to throw "requires at least one TabItem". Return null instead.
221+ if ( ! schemaArray || ! Array . isArray ( schemaArray ) || schemaArray . length === 0 ) {
222+ return null ;
223+ }
224+
217225 const type = schema . oneOf
218226 ? translate ( { id : OPENAPI_SCHEMA_ITEM . ONE_OF , message : "oneOf" } )
219227 : translate ( { id : OPENAPI_SCHEMA_ITEM . ANY_OF , message : "anyOf" } ) ;
Original file line number Diff line number Diff line change @@ -223,16 +223,43 @@ function TabsComponent(props: SchemaTabsProps): React.JSX.Element {
223223 </ div >
224224 ) ;
225225}
226- export default function SchemaTabs ( props : SchemaTabsProps ) : React . JSX . Element {
226+ export default function SchemaTabs (
227+ props : SchemaTabsProps
228+ ) : React . JSX . Element | null {
227229 const isBrowser = useIsBrowser ( ) ;
230+
231+ const children = Array . isArray ( props . children )
232+ ? props . children . filter ( Boolean )
233+ : props . children
234+ ? [ props . children ]
235+ : [ ] ;
236+
237+ if ( children . length === 0 ) {
238+ return null ;
239+ }
240+
241+ let sanitizedChildren ;
242+ try {
243+ sanitizedChildren = sanitizeTabsChildren ( children ) ;
244+ } catch {
245+ return null ;
246+ }
247+
248+ if (
249+ ! sanitizedChildren ||
250+ ( Array . isArray ( sanitizedChildren ) && sanitizedChildren . length === 0 )
251+ ) {
252+ return null ;
253+ }
254+
228255 return (
229256 < TabsComponent
230257 // Remount tabs after hydration
231258 // Temporary fix for https://github.com/facebook/docusaurus/issues/5653
232259 key = { String ( isBrowser ) }
233260 { ...props }
234261 >
235- { sanitizeTabsChildren ( props . children ) }
262+ { sanitizedChildren }
236263 </ TabsComponent >
237264 ) ;
238265}
You can’t perform that action at this time.
0 commit comments