Skip to content

Commit d9db2e4

Browse files
committed
Use context to track depth of nested islands
1 parent e1b3eba commit d9db2e4

File tree

2 files changed

+35
-10
lines changed

2 files changed

+35
-10
lines changed

dotcom-rendering/src/components/Island.tsx

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import { useContext } from 'react';
12
import type { ScheduleOptions, SchedulePriority } from '../lib/scheduler';
3+
import { IslandDepthContext } from './IslandDepthContext';
24

35
type DeferredProps = {
46
visible: {
@@ -55,17 +57,31 @@ export const Island = ({ priority, defer, children, role }: IslandProps) => {
5557
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- Type definitions on children are limited
5658
const name = String(children.type.name);
5759

60+
/**
61+
* Current depth of island if nested within another island. This is used so
62+
* that we only hydrate top-level islands which are then responsible for
63+
* hydrating the entire subtree and any child islands.
64+
*/
65+
const islandDepth = useContext(IslandDepthContext);
66+
5867
return (
59-
<gu-island
60-
name={name}
61-
priority={priority}
62-
deferUntil={defer?.until}
63-
props={JSON.stringify(children.props)}
64-
rootMargin={rootMargin}
65-
data-spacefinder-role={role}
66-
>
67-
{children}
68-
</gu-island>
68+
<IslandDepthContext.Provider value={islandDepth + 1}>
69+
{/* Child islands defer to nearest parent island for hydration */}
70+
{islandDepth > 0 ? (
71+
children
72+
) : (
73+
<gu-island
74+
name={name}
75+
priority={priority}
76+
deferUntil={defer?.until}
77+
props={JSON.stringify(children.props)}
78+
rootMargin={rootMargin}
79+
data-spacefinder-role={role}
80+
>
81+
{children}
82+
</gu-island>
83+
)}
84+
</IslandDepthContext.Provider>
6985
);
7086
};
7187

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { createContext } from 'react';
2+
3+
/**
4+
* Context to track the depth of islands in the component tree. This is used to
5+
* prevent wrapping nested islands with `gu-island` and hydrating child islands
6+
* separately from their parent. When islands are nested the parent island is
7+
* responsible for hydrating the entire subtree.
8+
*/
9+
export const IslandDepthContext = createContext<number>(0);

0 commit comments

Comments
 (0)