Skip to content

Commit 2be7654

Browse files
committed
Fixed react-rendering before PluginContext is initialized
1 parent 21f19c6 commit 2be7654

File tree

2 files changed

+25
-4
lines changed

2 files changed

+25
-4
lines changed

src/app/ui/split-ui/split-ui.tsx

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { PluginReactContext } from 'Molstar/mol-plugin-ui/base';
33
import { PluginUIContext } from 'Molstar/mol-plugin-ui/context';
44
import { PluginUISpec } from 'Molstar/mol-plugin-ui/spec';
5-
import { ComponentProps, JSXElementConstructor, createElement } from 'react';
5+
import { ComponentProps, JSXElementConstructor, createElement, useEffect, useState } from 'react';
66
import { createRoot } from 'react-dom/client';
77
import { DefaultPluginUISpec } from '../../spec';
88

@@ -36,9 +36,6 @@ export async function createPluginSplitUI(options: {
3636
if (onBeforeUIRender) {
3737
await onBeforeUIRender(ctx);
3838
}
39-
if (!ctx.isInitialized) {
40-
throw new Error('NotImplementedError: React-rendering before PluginContext is initialized'); // TODO implement a la src/mol-plugin-ui/plugin.tsx
41-
}
4239
for (const { target: element, component, props } of layout) {
4340
render(<PluginPanelWrapper plugin={ctx} component={component} props={props ?? {}} />, resolveHTMLElement(element));
4441
// TODO in future: consider adding a listener that re-renders the React component when the div is removed and re-added to DOM
@@ -61,8 +58,28 @@ export function resolveHTMLElement(element: HTMLElement | string): HTMLElement {
6158
}
6259
}
6360

61+
type LoadState = { kind: 'initialized' } | { kind: 'pending' } | { kind: 'error', message: string }
6462

6563
function PluginPanelWrapper<P extends {}>({ plugin, component, props }: { plugin: PluginUIContext, component: JSXElementConstructor<P>, props: P }) {
64+
const [state, setState] = useState<LoadState>({ kind: 'pending' });
65+
useEffect(() => {
66+
setState(plugin.isInitialized ? { kind: 'initialized' } : { kind: 'pending' });
67+
let mounted = true;
68+
plugin.initialized.then(() => {
69+
if (mounted) setState({ kind: 'initialized' });
70+
}).catch(err => {
71+
if (mounted) setState({ kind: 'error', message: `${err}` });
72+
});
73+
return () => { mounted = false; };
74+
}, [plugin]);
75+
76+
if (state.kind !== 'initialized') {
77+
const message = state.kind === 'error' ? `Initialization error: ${state.message}` : 'Waiting for plugin initialization';
78+
return <div className='msp-plugin' style={{ position: 'relative', width: '100%', height: '100%' }}>
79+
<div className='msp-plugin-init-error'>{message}</div>
80+
</div>;
81+
}
82+
6683
return <PluginReactContext.Provider value={plugin}>
6784
<div className='msp-plugin' style={{ position: 'relative', width: '100%', height: '100%' }}>
6885
<div className='msp-plugin-content msp-layout-standard' style={{ position: 'relative', width: '100%', height: '100%' }}>

src/overlay.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,7 @@ svg.pdbe-animated-logo {
4848
border: solid 1px transparent;
4949
background-clip: content-box;
5050
}
51+
52+
.msp-plugin .msp-plugin-init-error{
53+
color: #808080;
54+
}

0 commit comments

Comments
 (0)