Skip to content

Commit 351191b

Browse files
authored
feat(swagger-ui-react): rewrite into SSR compatible function component (#9855)
Refs #9243
1 parent fee426b commit 351191b

File tree

1 file changed

+116
-110
lines changed

1 file changed

+116
-110
lines changed

flavors/swagger-ui-react/index.jsx

Lines changed: 116 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,138 @@
1-
import React from "react"
1+
/**
2+
* @prettier
3+
*/
4+
"use client"
5+
6+
import React, { useEffect, useCallback, useState } from "react"
27
import PropTypes from "prop-types"
38
import SwaggerUIConstructor from "#swagger-ui"
49

5-
class SwaggerUI extends React.Component {
6-
constructor (props) {
7-
super(props)
8-
this.SwaggerUIComponent = null
9-
this.system = null
10-
}
11-
12-
componentDidMount() {
13-
const ui = SwaggerUIConstructor({
14-
plugins: this.props.plugins,
15-
spec: this.props.spec,
16-
url: this.props.url,
17-
dom_id: null,
18-
domNode: null,
19-
layout: this.props.layout,
20-
defaultModelsExpandDepth: this.props.defaultModelsExpandDepth,
21-
defaultModelRendering: this.props.defaultModelRendering,
22-
presets: [SwaggerUIConstructor.presets.apis, ...this.props.presets],
23-
requestInterceptor: this.props.requestInterceptor,
24-
responseInterceptor: this.props.responseInterceptor,
25-
onComplete: this.onComplete,
26-
docExpansion: this.props.docExpansion,
27-
supportedSubmitMethods: this.props.supportedSubmitMethods,
28-
queryConfigEnabled: this.props.queryConfigEnabled,
29-
defaultModelExpandDepth: this.props.defaultModelExpandDepth,
30-
displayOperationId: this.props.displayOperationId,
31-
tryItOutEnabled: this.props.tryItOutEnabled,
32-
displayRequestDuration: this.props.displayRequestDuration,
33-
requestSnippetsEnabled: this.props.requestSnippetsEnabled,
34-
requestSnippets: this.props.requestSnippets,
35-
showMutatedRequest: this.props.showMutatedRequest,
36-
deepLinking: this.props.deepLinking,
37-
showExtensions: this.props.showExtensions,
38-
showCommonExtensions: this.props.showCommonExtensions,
39-
filter: this.props.filter,
40-
persistAuthorization: this.props.persistAuthorization,
41-
withCredentials: this.props.withCredentials,
42-
...(typeof this.props.oauth2RedirectUrl === "string" ? { oauth2RedirectUrl: this.props.oauth2RedirectUrl} : {})
43-
})
44-
45-
this.system = ui
46-
this.SwaggerUIComponent = ui.getComponent("App", "root")
10+
const SwaggerUI = ({
11+
spec = SwaggerUIConstructor.defaultOptions.spec,
12+
url = SwaggerUIConstructor.defaultOptions.url,
13+
layout = SwaggerUIConstructor.defaultOptions.layout,
14+
requestInterceptor = SwaggerUIConstructor.defaultOptions.requestInterceptor,
15+
responseInterceptor = SwaggerUIConstructor.defaultOptions.responseInterceptor,
16+
supportedSubmitMethods = SwaggerUIConstructor.defaultOptions
17+
.supportedSubmitMethods,
18+
queryConfigEnabled = SwaggerUIConstructor.defaultOptions.queryConfigEnabled,
19+
plugins = SwaggerUIConstructor.defaultOptions.plugins,
20+
displayOperationId = SwaggerUIConstructor.defaultOptions.displayOperationId,
21+
showMutatedRequest = SwaggerUIConstructor.defaultOptions.showMutatedRequest,
22+
docExpansion = SwaggerUIConstructor.defaultOptions.docExpansion,
23+
defaultModelExpandDepth = SwaggerUIConstructor.defaultOptions
24+
.defaultModelExpandDepth,
25+
defaultModelsExpandDepth = SwaggerUIConstructor.defaultOptions
26+
.defaultModelsExpandDepth,
27+
defaultModelRendering = SwaggerUIConstructor.defaultOptions
28+
.defaultModelRendering,
29+
presets = SwaggerUIConstructor.defaultOptions.presets,
30+
deepLinking = SwaggerUIConstructor.defaultOptions.deepLinking,
31+
showExtensions = SwaggerUIConstructor.defaultOptions.showExtensions,
32+
showCommonExtensions = SwaggerUIConstructor.defaultOptions
33+
.showCommonExtensions,
34+
filter = SwaggerUIConstructor.defaultOptions.filter,
35+
requestSnippetsEnabled = SwaggerUIConstructor.defaultOptions
36+
.requestSnippetsEnabled,
37+
requestSnippets = SwaggerUIConstructor.defaultOptions.requestSnippets,
38+
tryItOutEnabled = SwaggerUIConstructor.defaultOptions.tryItOutEnabled,
39+
displayRequestDuration = SwaggerUIConstructor.defaultOptions
40+
.displayRequestDuration,
41+
withCredentials = SwaggerUIConstructor.defaultOptions.withCredentials,
42+
persistAuthorization = SwaggerUIConstructor.defaultOptions
43+
.persistAuthorization,
44+
oauth2RedirectUrl = SwaggerUIConstructor.defaultOptions.oauth2RedirectUrl,
45+
onComplete = null,
46+
}) => {
47+
const [system, setSystem] = useState(null)
48+
const SwaggerUIComponent = system?.getComponent("App", "root")
4749

48-
this.forceUpdate()
49-
}
50-
51-
render() {
52-
return this.SwaggerUIComponent ? <this.SwaggerUIComponent /> : null
53-
}
50+
const handleComplete = useCallback(() => {
51+
if (typeof onComplete === "function") {
52+
onComplete()
53+
}
54+
}, [onComplete])
5455

55-
componentDidUpdate(prevProps) {
56-
const prevStateUrl = this.system.specSelectors.url()
57-
if(this.props.url !== prevStateUrl || this.props.url !== prevProps.url) {
58-
// flush current content
59-
this.system.specActions.updateSpec("")
56+
useEffect(() => {
57+
setSystem(
58+
SwaggerUIConstructor({
59+
plugins,
60+
spec,
61+
url,
62+
dom_id: null,
63+
domNode: null,
64+
layout,
65+
defaultModelsExpandDepth,
66+
defaultModelRendering,
67+
presets: [SwaggerUIConstructor.presets.apis, ...presets],
68+
requestInterceptor,
69+
responseInterceptor,
70+
onComplete: handleComplete,
71+
docExpansion,
72+
supportedSubmitMethods,
73+
queryConfigEnabled,
74+
defaultModelExpandDepth,
75+
displayOperationId,
76+
tryItOutEnabled,
77+
displayRequestDuration,
78+
requestSnippetsEnabled,
79+
requestSnippets,
80+
showMutatedRequest,
81+
deepLinking,
82+
showExtensions,
83+
showCommonExtensions,
84+
filter,
85+
persistAuthorization,
86+
withCredentials,
87+
...(typeof oauth2RedirectUrl === "string"
88+
? { oauth2RedirectUrl: oauth2RedirectUrl }
89+
: {}),
90+
})
91+
)
92+
}, [])
6093

61-
if(this.props.url) {
62-
// update the internal URL
63-
this.system.specActions.updateUrl(this.props.url)
64-
// trigger remote definition fetch
65-
this.system.specActions.download(this.props.url)
94+
useEffect(() => {
95+
if (system) {
96+
const prevStateUrl = system.specSelectors.url()
97+
if (url !== prevStateUrl) {
98+
system.specActions.updateSpec("")
99+
if (url) {
100+
system.specActions.updateUrl(url)
101+
system.specActions.download(url)
102+
}
66103
}
67-
}
68104

69-
const prevStateSpec = this.system.specSelectors.specStr()
70-
if(this.props.spec && (this.props.spec !== prevStateSpec || this.props.spec !== prevProps.spec)) {
71-
if(typeof this.props.spec === "object") {
72-
this.system.specActions.updateSpec(JSON.stringify(this.props.spec))
73-
} else {
74-
this.system.specActions.updateSpec(this.props.spec)
105+
const prevStateSpec = system.specSelectors.specStr()
106+
if (spec && spec !== prevStateSpec) {
107+
const updatedSpec =
108+
typeof spec === "object" ? JSON.stringify(spec) : spec
109+
system.specActions.updateSpec(updatedSpec)
75110
}
76111
}
77-
}
112+
}, [url, spec])
78113

79-
onComplete = () => {
80-
if (typeof this.props.onComplete === "function") {
81-
return this.props.onComplete(this.system)
82-
}
83-
}
114+
return SwaggerUIComponent ? <SwaggerUIComponent /> : null
84115
}
85116

86117
SwaggerUI.propTypes = {
87-
spec: PropTypes.oneOfType([
88-
PropTypes.string,
89-
PropTypes.object,
90-
]),
118+
spec: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
91119
url: PropTypes.string,
92120
layout: PropTypes.string,
93121
requestInterceptor: PropTypes.func,
94122
responseInterceptor: PropTypes.func,
95123
onComplete: PropTypes.func,
96124
docExpansion: PropTypes.oneOf(["list", "full", "none"]),
97125
supportedSubmitMethods: PropTypes.arrayOf(
98-
PropTypes.oneOf(["get", "put", "post", "delete", "options", "head", "patch", "trace"])
126+
PropTypes.oneOf([
127+
"get",
128+
"put",
129+
"post",
130+
"delete",
131+
"options",
132+
"head",
133+
"patch",
134+
"trace",
135+
])
99136
),
100137
queryConfigEnabled: PropTypes.bool,
101138
plugins: PropTypes.oneOfType([
@@ -112,10 +149,7 @@ SwaggerUI.propTypes = {
112149
deepLinking: PropTypes.bool,
113150
showExtensions: PropTypes.bool,
114151
showCommonExtensions: PropTypes.bool,
115-
filter: PropTypes.oneOfType([
116-
PropTypes.string,
117-
PropTypes.bool,
118-
]),
152+
filter: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
119153
requestSnippetsEnabled: PropTypes.bool,
120154
requestSnippets: PropTypes.object,
121155
tryItOutEnabled: PropTypes.bool,
@@ -125,37 +159,9 @@ SwaggerUI.propTypes = {
125159
oauth2RedirectUrl: PropTypes.string,
126160
}
127161

128-
SwaggerUI.defaultProps = {
129-
spec: SwaggerUIConstructor.defaultOptions.spec,
130-
url: SwaggerUIConstructor.defaultOptions.url,
131-
layout: SwaggerUIConstructor.defaultOptions.layout,
132-
requestInterceptor: SwaggerUIConstructor.defaultOptions.requestInterceptor,
133-
responseInterceptor: SwaggerUIConstructor.defaultOptions.responseInterceptor,
134-
supportedSubmitMethods: SwaggerUIConstructor.defaultOptions.supportedSubmitMethods,
135-
queryConfigEnabled: SwaggerUIConstructor.defaultOptions.queryConfigEnabled,
136-
plugins: SwaggerUIConstructor.defaultOptions.plugins,
137-
displayOperationId: SwaggerUIConstructor.defaultOptions.displayOperationId,
138-
showMutatedRequest: SwaggerUIConstructor.defaultOptions.showMutatedRequest,
139-
docExpansion: SwaggerUIConstructor.defaultOptions.docExpansion,
140-
defaultModelExpandDepth: SwaggerUIConstructor.defaultOptions.defaultModelExpandDepth,
141-
defaultModelsExpandDepth: SwaggerUIConstructor.defaultOptions.defaultModelsExpandDepth,
142-
defaultModelRendering: SwaggerUIConstructor.defaultOptions.defaultModelRendering,
143-
presets: SwaggerUIConstructor.defaultOptions.presets,
144-
deepLinking: SwaggerUIConstructor.defaultOptions.deepLinking,
145-
showExtensions: SwaggerUIConstructor.defaultOptions.showExtensions,
146-
showCommonExtensions: SwaggerUIConstructor.defaultOptions.showCommonExtensions,
147-
filter: SwaggerUIConstructor.defaultOptions.filter,
148-
requestSnippetsEnabled: SwaggerUIConstructor.defaultOptions.requestSnippetsEnabled,
149-
requestSnippets: SwaggerUIConstructor.defaultOptions.requestSnippets,
150-
tryItOutEnabled: SwaggerUIConstructor.defaultOptions.tryItOutEnabled,
151-
displayRequestDuration: SwaggerUIConstructor.defaultOptions.displayRequestDuration,
152-
withCredentials: SwaggerUIConstructor.defaultOptions.withCredentials,
153-
persistAuthorization: SwaggerUIConstructor.defaultOptions.persistAuthorization,
154-
oauth2RedirectUrl: undefined,
155-
}
156-
157162
SwaggerUI.System = SwaggerUIConstructor.System
158163
SwaggerUI.presets = SwaggerUIConstructor.presets
159164
SwaggerUI.plugins = SwaggerUIConstructor.plugins
165+
SwaggerUI.defaultOptions = SwaggerUIConstructor.defaultOptions
160166

161167
export default SwaggerUI

0 commit comments

Comments
 (0)