diff --git a/src/components/Responses/Response.tsx b/src/components/Responses/Response.tsx
index bc6ece8b..d9c11d32 100644
--- a/src/components/Responses/Response.tsx
+++ b/src/components/Responses/Response.tsx
@@ -1,40 +1,47 @@
-import { observer } from 'mobx-react';
import * as React from 'react';
+import { observer } from 'mobx-react';
-import { ResponseModel } from '../../services/models';
+import type { ResponseModel, MediaTypeModel } from '../../services/models';
import { ResponseDetails } from './ResponseDetails';
import { ResponseDetailsWrap, StyledResponseTitle } from './styled.elements';
-@observer
-export class ResponseView extends React.Component<{ response: ResponseModel }> {
- toggle = () => {
- this.props.response.toggle();
- };
-
- render() {
- const { extensions, headers, type, summary, description, code, expanded, content } = this.props.response;
- const mimes =
- content === undefined ? [] : content.mediaTypes.filter(mime => mime.schema !== undefined);
-
- const empty = (!extensions || Object.keys(extensions).length === 0) &&
- headers.length === 0 && mimes.length === 0 && !description;
-
- return (
-
-
- {expanded && !empty && (
-
-
-
- )}
-
- );
- }
+export interface ResponseViewProps {
+ response: ResponseModel;
}
+
+export const ResponseView = observer(({ response }: ResponseViewProps): React.ReactElement => {
+ const { extensions, headers, type, summary, description, code, expanded, content } = response;
+
+ const mimes = React.useMemo(
+ () =>
+ content === undefined ? [] : content.mediaTypes.filter(mime => mime.schema !== undefined),
+ [content],
+ );
+
+ const empty = React.useMemo(
+ () =>
+ (!extensions || Object.keys(extensions).length === 0) &&
+ headers.length === 0 &&
+ mimes.length === 0 &&
+ !description,
+ [extensions, headers, mimes, description],
+ );
+
+ return (
+
+
+ {expanded && !empty && (
+
+
+
+ )}
+
+ );
+});
diff --git a/src/components/Responses/ResponseTitle.tsx b/src/components/Responses/ResponseTitle.tsx
index 74e07a39..812bbccd 100644
--- a/src/components/Responses/ResponseTitle.tsx
+++ b/src/components/Responses/ResponseTitle.tsx
@@ -14,27 +14,34 @@ export interface ResponseTitleProps {
onClick?: () => void;
}
-export class ResponseTitle extends React.PureComponent {
- render() {
- const { title, type, empty, code, opened, className, onClick } = this.props;
- return (
-
- );
- }
+function ResponseTitleComponent({
+ title,
+ type,
+ empty,
+ code,
+ opened,
+ className,
+ onClick,
+}: ResponseTitleProps): React.ReactElement {
+ return (
+
+ );
}
+
+export const ResponseTitle = React.memo(ResponseTitleComponent);
diff --git a/src/components/Responses/styled.elements.ts b/src/components/Responses/styled.elements.ts
index 531236dd..7e456870 100644
--- a/src/components/Responses/styled.elements.ts
+++ b/src/components/Responses/styled.elements.ts
@@ -11,14 +11,12 @@ export const StyledResponseTitle = styled(ResponseTitle)`
border-radius: 2px;
margin-bottom: 4px;
line-height: 1.5em;
- background-color: #f2f2f2;
cursor: pointer;
color: ${props => props.theme.colors.responses[props.type].color};
background-color: ${props => props.theme.colors.responses[props.type].backgroundColor};
&:focus {
- outline: auto;
- outline-color: ${props => props.theme.colors.responses[props.type].color};
+ outline: auto ${props => props.theme.colors.responses[props.type].color};
}
${props =>
(props.empty &&
diff --git a/src/services/__tests__/models/Response.test.ts b/src/services/__tests__/models/Response.test.ts
index 48633619..26ec21b7 100644
--- a/src/services/__tests__/models/Response.test.ts
+++ b/src/services/__tests__/models/Response.test.ts
@@ -42,9 +42,16 @@ describe('Models', () => {
test('ensure extensions are shown if showExtensions is true', () => {
const options = new RedocNormalizedOptions({ showExtensions: true });
- const resp = new ResponseModel(parser, 'default', true, { 'x-example': {a: 1} } as any, options);
+ const resp = new ResponseModel({
+ parser,
+ code: 'default',
+ defaultAsError: true,
+ infoOrRef: { 'x-example': { a: 1 } },
+ options,
+ isEvent: true,
+ });
expect(Object.keys(resp.extensions).length).toEqual(1);
- expect(resp.extensions['x-example']).toEqual({a: 1});
+ expect(resp.extensions['x-example']).toEqual({ a: 1 });
});
});
});
diff --git a/src/services/models/RequestBody.ts b/src/services/models/RequestBody.ts
index b7f209d6..18780a58 100644
--- a/src/services/models/RequestBody.ts
+++ b/src/services/models/RequestBody.ts
@@ -17,8 +17,7 @@ export class RequestBodyModel {
required: boolean;
content?: MediaContentModel;
- constructor(props: RequestBodyProps) {
- const { parser, infoOrRef, options, isEvent } = props;
+ constructor({ parser, infoOrRef, options, isEvent }: RequestBodyProps) {
const isRequest = !isEvent;
const info = parser.deref(infoOrRef);
this.description = info.description || '';
diff --git a/src/services/models/Response.ts b/src/services/models/Response.ts
index a0878093..77159a8a 100644
--- a/src/services/models/Response.ts
+++ b/src/services/models/Response.ts
@@ -2,10 +2,7 @@ import { action, observable, makeObservable } from 'mobx';
import { OpenAPIResponse, Referenced } from '../../types';
-import {
- getStatusCodeType,
- extractExtensions
-} from '../../utils';
+import { getStatusCodeType, extractExtensions } from '../../utils';
import { OpenAPIParser } from '../OpenAPIParser';
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
import { FieldModel } from './Field';
@@ -32,9 +29,14 @@ export class ResponseModel {
headers: FieldModel[] = [];
extensions: Record;
- constructor(props: ResponseProps) {
- const { parser, code, defaultAsError, infoOrRef, options, isEvent } = props;
- const isRequest = isEvent ? true : false;
+ constructor({
+ parser,
+ code,
+ defaultAsError,
+ infoOrRef,
+ options,
+ isEvent: isRequest,
+ }: ResponseProps) {
makeObservable(this);
this.expanded = options.expandResponses === 'all' || options.expandResponses[code];