Skip to content

Commit

Permalink
fix(component): fix lit portal not re-rendering in inline links case
Browse files Browse the repository at this point in the history
  • Loading branch information
fundon committed Dec 26, 2024
1 parent 2ffd0e5 commit 2d40aab
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 43 deletions.
105 changes: 64 additions & 41 deletions packages/frontend/component/src/lit-react/lit-portal/lite-portal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,26 @@ type PortalEvent = {
};

type PortalListener = (event: PortalEvent) => void;
const listeners: Set<PortalListener> = new Set();

export function createLitPortalAnchor(callback: (event: PortalEvent) => void) {
const id = nanoid();
// todo(@Peng): clean up listeners?
listeners.add(event => {
if (event.target.portalId !== id) {
return;
}
callback(event);
});
return html`<lit-react-portal portalId=${id}></lit-react-portal>`;
return html`<lit-react-portal
.notify=${callback}
portalId=${nanoid()}
></lit-react-portal>`;
}

export const LIT_REACT_PORTAL = 'lit-react-portal';

@customElement(LIT_REACT_PORTAL)
class LitReactPortal extends LitElement {
portalId: string = '';
portalId!: string;

notify!: PortalListener;

static override get properties() {
return {
portalId: { type: String },
notify: { attribute: false },
};
}

Expand All @@ -44,13 +41,11 @@ class LitReactPortal extends LitElement {
) {
super.attributeChangedCallback(name, oldVal, newVal);
if (name.toLowerCase() === 'portalid') {
listeners.forEach(l =>
l({
name: 'willUpdate',
target: this,
previousPortalId: oldVal,
})
);
this.notify({
name: 'willUpdate',
target: this,
previousPortalId: oldVal,
});
}
}

Expand All @@ -60,22 +55,18 @@ class LitReactPortal extends LitElement {
}

override connectedCallback() {
listeners.forEach(l =>
l({
name: 'connectedCallback',
target: this,
})
);
this.notify({
name: 'connectedCallback',
target: this,
});
}

override disconnectedCallback() {
super.disconnectedCallback();
listeners.forEach(l =>
l({
name: 'disconnectedCallback',
target: this,
})
);
this.notify({
name: 'disconnectedCallback',
target: this,
});
}
}

Expand All @@ -98,24 +89,56 @@ export const useLitPortalFactory = () => {

return [
useCallback(
(elementOrFactory: React.ReactElement | (() => React.ReactElement)) => {
(
elementOrFactory: React.ReactElement | (() => React.ReactElement),
rerendering = true
) => {
const element =
typeof elementOrFactory === 'function'
? elementOrFactory()
: elementOrFactory;
return createLitPortalAnchor(event => {
const portalId = event.target.portalId;
const { name, target } = event;
const id = target.portalId;

if (name === 'connectedCallback') {
setPortals(portals => [
...portals,
{
id,
portal: ReactDOM.createPortal(element, target, id),
},
]);
return;
}

if (name === 'disconnectedCallback') {
setPortals(portals => portals.filter(p => p.id !== id));
return;
}

const prevId = event.previousPortalId;

// Ignores first `willUpdate`
if (!prevId) {
return;
}

setPortals(portals => {
const newPortals = portals.filter(
p => p.id !== event.previousPortalId && p.id !== portalId
);
if (event.name !== 'disconnectedCallback') {
newPortals.push({
id: portalId,
portal: ReactDOM.createPortal(element, event.target),
});
const portal = portals.find(p => p.id === prevId);
if (!portal) return [...portals];

// Updates `ID`
portal.id = id;

// Re-rendering
// true: `inline link`
// false: `pdf embed view`
if (rerendering) {
portal.portal = ReactDOM.createPortal(element, target, id);
}
return newPortals;

return [...portals];
});
});
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ export const BiDirectionalLinkPanel = () => {
{
<>
{portals.map(p => (
<Fragment key={p.id}>{p.portal}</Fragment>
<Fragment key={p.portal.key}>{p.portal}</Fragment>
))}
</>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ const usePatchSpecs = (shared: boolean, mode: DocMode) => {
() => (
<>
{portals.map(p => (
<Fragment key={p.id}>{p.portal}</Fragment>
<Fragment key={p.portal.key}>{p.portal}</Fragment>
))}
</>
),
Expand Down

0 comments on commit 2d40aab

Please sign in to comment.