|
@@ -1,9 +1,9 @@
|
|
|
-import {Component, lazy, Suspense} from 'react';
|
|
|
+import {ComponentProps, lazy, Suspense, useEffect, useState} from 'react';
|
|
|
|
|
|
import HookStore from 'sentry/stores/hookStore';
|
|
|
import {HookName, Hooks} from 'sentry/types/hooks';
|
|
|
|
|
|
-type Params<H extends HookName> = {
|
|
|
+interface Params<H extends HookName> {
|
|
|
/**
|
|
|
* The name of the hook as listed in hookstore.add(hookName, callback)
|
|
|
*/
|
|
@@ -18,7 +18,7 @@ type Params<H extends HookName> = {
|
|
|
* use React.Suspense and React.lazy to render the component.
|
|
|
*/
|
|
|
defaultComponentPromise?: () => Promise<ReturnType<Hooks[H]>>;
|
|
|
-};
|
|
|
+}
|
|
|
|
|
|
/**
|
|
|
* Use this instead of the usual ternery operator when using getsentry hooks.
|
|
@@ -46,54 +46,58 @@ function HookOrDefault<H extends HookName>({
|
|
|
hookName,
|
|
|
defaultComponent,
|
|
|
defaultComponentPromise,
|
|
|
-}: Params<H>) {
|
|
|
- type Props = React.ComponentProps<ReturnType<Hooks[H]>>;
|
|
|
- type State = {hooks: Hooks[H][]};
|
|
|
-
|
|
|
- class HookOrDefaultComponent extends Component<Props, State> {
|
|
|
- static displayName = `HookOrDefaultComponent(${hookName})`;
|
|
|
+}: Params<H>): React.FunctionComponent<ComponentProps<ReturnType<Hooks[H]>>> {
|
|
|
+ type Props = ComponentProps<ReturnType<Hooks[H]>>;
|
|
|
|
|
|
- state: State = {
|
|
|
- hooks: HookStore.get(hookName),
|
|
|
- };
|
|
|
+ // Defining the props here is unnecessary and slow for typescript
|
|
|
+ function getDefaultComponent(): React.ComponentType<any> | undefined {
|
|
|
+ // If `defaultComponentPromise` is passed, then return a Suspended component
|
|
|
+ if (defaultComponentPromise) {
|
|
|
+ // Lazy adds a complicated type that is not important
|
|
|
+ const DefaultComponent: React.ComponentType<any> = lazy(defaultComponentPromise);
|
|
|
|
|
|
- componentWillUnmount() {
|
|
|
- this.unlistener?.();
|
|
|
+ return function (props: Props) {
|
|
|
+ return (
|
|
|
+ <Suspense fallback={null}>
|
|
|
+ <DefaultComponent {...props} />
|
|
|
+ </Suspense>
|
|
|
+ );
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
- unlistener = HookStore.listen(
|
|
|
- (name: string, hooks: Hooks[HookName][]) =>
|
|
|
- name === hookName && this.setState({hooks}),
|
|
|
- undefined
|
|
|
- );
|
|
|
+ return defaultComponent;
|
|
|
+ }
|
|
|
|
|
|
- get defaultComponent() {
|
|
|
- // If `defaultComponentPromise` is passed, then return a Suspended component
|
|
|
- if (defaultComponentPromise) {
|
|
|
- const DefaultComponent = lazy(defaultComponentPromise);
|
|
|
+ function HookOrDefaultComponent(props: Props) {
|
|
|
+ const [hooks, setHooks] = useState<Hooks[H][]>(HookStore.get(hookName));
|
|
|
|
|
|
- return function (props: Props) {
|
|
|
- return (
|
|
|
- <Suspense fallback={null}>
|
|
|
- <DefaultComponent {...props} />
|
|
|
- </Suspense>
|
|
|
- );
|
|
|
- };
|
|
|
- }
|
|
|
+ useEffect(() => {
|
|
|
+ const unsubscribe = HookStore.listen((name: string, newHooks: Hooks[H][]) => {
|
|
|
+ if (name === hookName) {
|
|
|
+ setHooks(newHooks);
|
|
|
+ }
|
|
|
+ }, undefined);
|
|
|
|
|
|
- return defaultComponent;
|
|
|
- }
|
|
|
+ return () => {
|
|
|
+ unsubscribe();
|
|
|
+ };
|
|
|
+ }, []);
|
|
|
|
|
|
- render() {
|
|
|
- const hookExists = this.state.hooks && this.state.hooks.length;
|
|
|
- const componentFromHook = this.state.hooks[0]?.();
|
|
|
- const HookComponent =
|
|
|
- hookExists && componentFromHook ? componentFromHook : this.defaultComponent;
|
|
|
+ const hookExists = hooks && hooks.length;
|
|
|
+ const componentFromHook = hooks[0]?.();
|
|
|
+ // Defining the props here is unnecessary and slow for typescript
|
|
|
+ const HookComponent: React.ComponentType<any> =
|
|
|
+ hookExists && componentFromHook ? componentFromHook : getDefaultComponent();
|
|
|
|
|
|
- return HookComponent ? <HookComponent {...this.props} /> : null;
|
|
|
+ if (!HookComponent) {
|
|
|
+ return null;
|
|
|
}
|
|
|
+
|
|
|
+ return <HookComponent {...props} />;
|
|
|
}
|
|
|
|
|
|
+ HookOrDefaultComponent.displayName = `HookOrDefaultComponent(${hookName})`;
|
|
|
+
|
|
|
return HookOrDefaultComponent;
|
|
|
}
|
|
|
|