chore: refactor StoreProvider to not use componentWillReceiveProps

This commit is contained in:
Roman Hotsiy 2018-06-25 12:47:09 +03:00
parent f404626802
commit 637b493b41
No known key found for this signature in database
GPG Key ID: 5CB7B3ACABA57CB0
2 changed files with 39 additions and 49 deletions

View File

@ -132,6 +132,7 @@
"lunr": "^2.3.0", "lunr": "^2.3.0",
"mark.js": "^8.11.1", "mark.js": "^8.11.1",
"marked": "0.3.18", "marked": "0.3.18",
"memoize-one": "^3.1.1",
"mobx": "^4.3.0", "mobx": "^4.3.0",
"mobx-react": "^5.2.3", "mobx-react": "^5.2.3",
"openapi-sampler": "1.0.0-beta.13", "openapi-sampler": "1.0.0-beta.13",

View File

@ -1,3 +1,4 @@
import memoize from 'memoize-one';
import { Component } from 'react'; import { Component } from 'react';
import { AppStore } from '../services/'; import { AppStore } from '../services/';
@ -18,77 +19,65 @@ export interface StoreProviderProps {
export interface StoreProviderState { export interface StoreProviderState {
error?: Error; error?: Error;
loading: boolean; loading: boolean;
store?: AppStore; spec?: any;
prevSpecUrl?: string;
} }
export class StoreProvider extends Component<StoreProviderProps, StoreProviderState> { export class StoreProvider extends Component<StoreProviderProps, StoreProviderState> {
store: AppStore; static getDerivedStateFromProps(props, state: StoreProviderState) {
if (props.specUrl !== state.prevSpecUrl) {
return {
spec: null,
prevSpecUrl: props.specUrl,
};
}
private _resolvedSpec: OpenAPISpec; return null;
}
constructor(props: StoreProviderProps) { state: StoreProviderState = {
super(props); loading: true,
spec: null,
};
this.state = { @memoize
loading: true, makeStore(spec, specUrl, options) {
}; if (!spec) {
return undefined;
}
return new AppStore(spec, specUrl, options);
} }
componentDidMount() { componentDidMount() {
this.load(); this.load();
} }
componentDidUpdate() {
if (this.props.spec === null) {
this.load();
}
}
async load() { async load() {
const { specUrl, spec, options } = this.props; const { specUrl, spec, options } = this.props;
this.setState({
loading: true,
});
try { try {
this._resolvedSpec = await loadAndBundleSpec(spec || specUrl!); const resolvedSpec = await loadAndBundleSpec(spec || specUrl!);
this.updateStore(this._resolvedSpec, specUrl, options); this.setState({ spec: resolvedSpec, loading: false });
} catch (e) { } catch (e) {
this.setState({ this.setState({ error: e });
error: e,
});
} }
} }
updateStore(resolvedSpec, specUrl, options) {
try {
this.setState({
loading: false,
store: new AppStore(resolvedSpec, specUrl, options),
error: undefined,
});
} catch (e) {
this.setState({
error: e,
});
}
}
componentWillReceiveProps(nextProps) {
if (this.props.specUrl !== nextProps.specUrl || this.props.spec !== nextProps.spec) {
setTimeout(() => this.load(), 0);
return;
}
if (this.props.options !== nextProps.options && this._resolvedSpec) {
this.updateStore(this._resolvedSpec, nextProps.specUrl, nextProps.options);
}
}
setError(e?: Error) {
this.setState({
error: e,
});
}
render() { render() {
if (this.state.error) { if (this.state.error) {
throw this.state.error; throw this.state.error;
} }
return this.props.children(this.state);
const { specUrl, options } = this.props;
const { loading, spec } = this.state;
return this.props.children({
loading,
store: this.makeStore(spec, specUrl, options),
});
} }
} }