Skip to content

Commit

Permalink
Fixed react-rendering before PluginContext is initialized
Browse files Browse the repository at this point in the history
  • Loading branch information
midlik committed Jul 2, 2024
1 parent 21f19c6 commit 2be7654
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 4 deletions.
25 changes: 21 additions & 4 deletions src/app/ui/split-ui/split-ui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { PluginReactContext } from 'Molstar/mol-plugin-ui/base';
import { PluginUIContext } from 'Molstar/mol-plugin-ui/context';
import { PluginUISpec } from 'Molstar/mol-plugin-ui/spec';
import { ComponentProps, JSXElementConstructor, createElement } from 'react';
import { ComponentProps, JSXElementConstructor, createElement, useEffect, useState } from 'react';
import { createRoot } from 'react-dom/client';
import { DefaultPluginUISpec } from '../../spec';

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

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

function PluginPanelWrapper<P extends {}>({ plugin, component, props }: { plugin: PluginUIContext, component: JSXElementConstructor<P>, props: P }) {
const [state, setState] = useState<LoadState>({ kind: 'pending' });
useEffect(() => {
setState(plugin.isInitialized ? { kind: 'initialized' } : { kind: 'pending' });
let mounted = true;
plugin.initialized.then(() => {
if (mounted) setState({ kind: 'initialized' });
}).catch(err => {
if (mounted) setState({ kind: 'error', message: `${err}` });
});
return () => { mounted = false; };
}, [plugin]);

if (state.kind !== 'initialized') {
const message = state.kind === 'error' ? `Initialization error: ${state.message}` : 'Waiting for plugin initialization';
return <div className='msp-plugin' style={{ position: 'relative', width: '100%', height: '100%' }}>
<div className='msp-plugin-init-error'>{message}</div>
</div>;
}

return <PluginReactContext.Provider value={plugin}>
<div className='msp-plugin' style={{ position: 'relative', width: '100%', height: '100%' }}>
<div className='msp-plugin-content msp-layout-standard' style={{ position: 'relative', width: '100%', height: '100%' }}>
Expand Down
4 changes: 4 additions & 0 deletions src/overlay.scss
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,7 @@ svg.pdbe-animated-logo {
border: solid 1px transparent;
background-clip: content-box;
}

.msp-plugin .msp-plugin-init-error{
color: #808080;
}

0 comments on commit 2be7654

Please sign in to comment.