diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/MethodEndpoint/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/MethodEndpoint/index.tsx index 95fc62dc8..752d65a61 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/MethodEndpoint/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/MethodEndpoint/index.tsx @@ -8,6 +8,7 @@ import React from "react"; import BrowserOnly from "@docusaurus/BrowserOnly"; +import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment"; import { useTypedSelector } from "@theme/ApiItem/hooks"; function colorForMethod(method: string) { @@ -38,6 +39,26 @@ export interface Props { } function MethodEndpoint({ method, path, context }: Props) { + // During SSR, render without Redux store access to avoid "Cannot read properties + // of null (reading 'store')" errors caused by useSelector running outside a Provider. + if (!ExecutionEnvironment.canUseDOM) { + return ( + <> +
+          
+            {method === "event" ? "Webhook" : method.toUpperCase()}
+          {" "}
+          {method !== "event" && (
+            

+ {`${path.replace(/{([a-z0-9-_]+)}/gi, ":$1")}`} +

+ )} +
+
+ + ); + } + let serverValue = useTypedSelector((state: any) => state.server.value); let serverUrlWithVariables = ""; diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/Schema/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/Schema/index.tsx index 051150e28..33c04441c 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/Schema/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/Schema/index.tsx @@ -214,6 +214,14 @@ const AnyOneOf: React.FC = ({ schemaPath, }) => { const key = schema.oneOf ? "oneOf" : "anyOf"; + const schemaArray = schema[key]; + + // Empty oneOf/anyOf arrays are valid in OpenAPI specs but would cause the + // Tabs component to throw "requires at least one TabItem". Return null instead. + if (!schemaArray || !Array.isArray(schemaArray) || schemaArray.length === 0) { + return null; + } + const type = schema.oneOf ? translate({ id: OPENAPI_SCHEMA_ITEM.ONE_OF, message: "oneOf" }) : translate({ id: OPENAPI_SCHEMA_ITEM.ANY_OF, message: "anyOf" }); diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/SchemaTabs/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/SchemaTabs/index.tsx index b94d12942..e96f9e83c 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/SchemaTabs/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/SchemaTabs/index.tsx @@ -223,8 +223,35 @@ function TabsComponent(props: SchemaTabsProps): React.JSX.Element {
); } -export default function SchemaTabs(props: SchemaTabsProps): React.JSX.Element { +export default function SchemaTabs( + props: SchemaTabsProps +): React.JSX.Element | null { const isBrowser = useIsBrowser(); + + const children = Array.isArray(props.children) + ? props.children.filter(Boolean) + : props.children + ? [props.children] + : []; + + if (children.length === 0) { + return null; + } + + let sanitizedChildren; + try { + sanitizedChildren = sanitizeTabsChildren(children); + } catch { + return null; + } + + if ( + !sanitizedChildren || + (Array.isArray(sanitizedChildren) && sanitizedChildren.length === 0) + ) { + return null; + } + return ( - {sanitizeTabsChildren(props.children)} + {sanitizedChildren} ); }