feat: pass error in init callback + onLoaded for RedocStandalone

This commit is contained in:
Roman Hotsiy 2018-06-25 13:48:51 +03:00
parent 637b493b41
commit 16313b8293
No known key found for this signature in database
GPG Key ID: 5CB7B3ACABA57CB0
4 changed files with 31 additions and 15 deletions

View File

@ -11,9 +11,10 @@ export interface RedocStandaloneProps {
spec?: object;
specUrl?: string;
options?: RedocRawOptions;
onLoaded?: (e?: Error) => any;
}
export class RedocStandalone extends React.Component<RedocStandaloneProps> {
export class RedocStandalone extends React.PureComponent<RedocStandaloneProps> {
static propTypes = {
spec: (props, _, componentName) => {
if (!props.spec && !props.specUrl) {
@ -36,14 +37,14 @@ export class RedocStandalone extends React.Component<RedocStandaloneProps> {
};
render() {
const { spec, specUrl, options = {} } = this.props;
const { spec, specUrl, options = {}, onLoaded } = this.props;
const hideLoading = options.hideLoading !== undefined;
const normalizedOpts = new RedocNormalizedOptions(options);
return (
<ErrorBoundary>
<StoreProvider spec={spec} specUrl={specUrl} options={options}>
<StoreProvider spec={spec} specUrl={specUrl} options={options} onLoaded={onLoaded}>
{({ loading, store }) =>
!loading ? (
<Redoc store={store!} />

View File

@ -13,22 +13,27 @@ export interface StoreProviderProps {
options?: RedocRawOptions;
onLoaded?: (e?: Error) => void;
children: (props: { loading: boolean; store?: AppStore }) => any;
}
export interface StoreProviderState {
error?: Error;
loading: boolean;
spec?: any;
resolvedSpec?: any;
prevSpec?: any;
prevSpecUrl?: string;
}
export class StoreProvider extends Component<StoreProviderProps, StoreProviderState> {
static getDerivedStateFromProps(props, state: StoreProviderState) {
if (props.specUrl !== state.prevSpecUrl) {
static getDerivedStateFromProps(nextProps: StoreProviderProps, prevState: StoreProviderState) {
if (nextProps.specUrl !== prevState.prevSpecUrl || nextProps.spec !== prevState.prevSpec) {
return {
spec: null,
prevSpecUrl: props.specUrl,
loading: true,
resolvedSpec: null,
prevSpec: nextProps.spec,
prevSpecUrl: nextProps.specUrl,
};
}
@ -37,7 +42,7 @@ export class StoreProvider extends Component<StoreProviderProps, StoreProviderSt
state: StoreProviderState = {
loading: true,
spec: null,
resolvedSpec: null,
};
@memoize
@ -53,8 +58,11 @@ export class StoreProvider extends Component<StoreProviderProps, StoreProviderSt
}
componentDidUpdate() {
if (this.props.spec === null) {
if (this.state.resolvedSpec === null) {
this.load();
} else if (!this.state.loading && this.props.onLoaded) {
// may run multiple time
this.props.onLoaded();
}
}
@ -62,8 +70,11 @@ export class StoreProvider extends Component<StoreProviderProps, StoreProviderSt
const { specUrl, spec, options } = this.props;
try {
const resolvedSpec = await loadAndBundleSpec(spec || specUrl!);
this.setState({ spec: resolvedSpec, loading: false });
this.setState({ resolvedSpec, loading: false });
} catch (e) {
if (this.props.onLoaded) {
this.props.onLoaded(e);
}
this.setState({ error: e });
}
}
@ -74,10 +85,10 @@ export class StoreProvider extends Component<StoreProviderProps, StoreProviderSt
}
const { specUrl, options } = this.props;
const { loading, spec } = this.state;
const { loading, resolvedSpec } = this.state;
return this.props.children({
loading,
store: this.makeStore(spec, specUrl, options),
store: this.makeStore(resolvedSpec, specUrl, options),
});
}
}

View File

@ -37,7 +37,7 @@ export function init(
specOrSpecUrl: string | any,
options: any = {},
element: Element | null = querySelector('redoc'),
callback?: () => void,
callback?: (e?: Error) => void,
) {
if (element === null) {
throw new Error('"element" argument is not provided and <redoc> tag is not found on the page');
@ -57,13 +57,13 @@ export function init(
RedocStandalone,
{
spec,
onLoaded: callback,
specUrl,
options: { ...options, ...parseOptionsFromElement(element) },
},
['Loading...'],
),
element,
callback,
);
}

View File

@ -5914,6 +5914,10 @@ mem@^1.1.0:
dependencies:
mimic-fn "^1.0.0"
memoize-one@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-3.1.1.tgz#ef609811e3bc28970eac2884eece64d167830d17"
memory-fs@^0.4.0, memory-fs@~0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"