Skip to content

Commit aef32fd

Browse files
committed
useDynamicRowHeight: Don't instantiate ResizeObserver when server-rendering
1 parent 69330f4 commit aef32fd

8 files changed

Lines changed: 121 additions & 10 deletions

File tree

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"use client";
2+
3+
import { List as ListExternal, useDynamicRowHeight } from "react-window";
4+
import { RowComponent } from "./RowComponent";
5+
6+
export function List() {
7+
const rowHeight = useDynamicRowHeight({
8+
defaultRowHeight: 30
9+
});
10+
11+
return (
12+
<ListExternal
13+
className="h-[250px]"
14+
defaultHeight={250}
15+
overscanCount={0}
16+
rowComponent={RowComponent}
17+
rowCount={100}
18+
rowHeight={rowHeight}
19+
rowProps={{}}
20+
/>
21+
);
22+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"use client";
2+
3+
import { type RowComponentProps } from "react-window";
4+
5+
export function RowComponent({
6+
ariaAttributes,
7+
index,
8+
style
9+
}: RowComponentProps<object>) {
10+
return (
11+
<div className="flex items-center gap-1" style={style} {...ariaAttributes}>
12+
Row {index}
13+
</div>
14+
);
15+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import {
2+
AnimationFrameRowCellCounter,
3+
EnvironmentMarker,
4+
LayoutShiftDetecter
5+
} from "../../../tests";
6+
import { List } from "./components/List";
7+
import { RowComponent } from "./components/RowComponent";
8+
9+
export default async function Home() {
10+
return (
11+
<div className="p-2 flex flex-col gap-2">
12+
<EnvironmentMarker>NextJS (server components)</EnvironmentMarker>
13+
<AnimationFrameRowCellCounter />
14+
<LayoutShiftDetecter />
15+
<List />
16+
</div>
17+
);
18+
}

integrations/next/app/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export default async function Home() {
44
return (
55
<div className="p-2 flex flex-col gap-2">
66
<Link href="/list">List</Link>
7+
<Link href="/list-dynamic">List + useDynamicRowHeight</Link>
78
<Link href="/grid">Grid</Link>
89
</div>
910
);

integrations/vike/pages/index/+Page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export default function Page() {
22
return (
33
<div className="p-2 flex flex-col gap-2">
44
<a href="/list">List</a>
5+
<a href="/list-dynamic">List + useDynamicRowHeight</a>
56
<a href="/grid">Grid</a>
67
</div>
78
);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { List, useDynamicRowHeight } from "react-window";
2+
import {
3+
AnimationFrameRowCellCounter,
4+
EnvironmentMarker,
5+
LayoutShiftDetecter
6+
} from "../../../tests";
7+
import { RowComponent } from "./RowComponent";
8+
9+
export default function Page() {
10+
const rowHeight = useDynamicRowHeight({
11+
defaultRowHeight: 30
12+
});
13+
14+
return (
15+
<div className="p-2 flex flex-col gap-2">
16+
<EnvironmentMarker>Vike (server rendering)</EnvironmentMarker>
17+
<AnimationFrameRowCellCounter />
18+
<LayoutShiftDetecter />
19+
<List
20+
className="h-[250px]"
21+
defaultHeight={250}
22+
overscanCount={0}
23+
rowComponent={RowComponent}
24+
rowCount={100}
25+
rowHeight={rowHeight}
26+
rowProps={{}}
27+
/>
28+
</div>
29+
);
30+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { type RowComponentProps } from "react-window";
2+
3+
export function RowComponent({
4+
ariaAttributes,
5+
index,
6+
style
7+
}: RowComponentProps<object>) {
8+
return (
9+
<div className="flex items-center gap-1" style={style} {...ariaAttributes}>
10+
Row {index}
11+
</div>
12+
);
13+
}

lib/components/list/useDynamicRowHeight.ts

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,22 +103,33 @@ export function useDynamicRowHeight({
103103
}
104104
);
105105

106-
const [resizeObserver] = useState(
107-
() => new ResizeObserver(resizeObserverCallback)
108-
);
106+
const [resizeObserver] = useState(() => {
107+
if (
108+
typeof window === "undefined" ||
109+
typeof ResizeObserver === "undefined"
110+
) {
111+
return null;
112+
}
113+
return new ResizeObserver(resizeObserverCallback);
114+
});
109115

110116
useEffect(() => {
111-
return () => {
112-
resizeObserver.disconnect();
113-
};
117+
if (resizeObserver) {
118+
return () => {
119+
resizeObserver.disconnect();
120+
};
121+
}
114122
}, [resizeObserver]);
115123

116124
const observeRowElements = useCallback(
117125
(elements: Element[] | NodeListOf<Element>) => {
118-
elements.forEach((element) => resizeObserver.observe(element));
119-
return () => {
120-
elements.forEach((element) => resizeObserver.unobserve(element));
121-
};
126+
if (resizeObserver) {
127+
elements.forEach((element) => resizeObserver.observe(element));
128+
return () => {
129+
elements.forEach((element) => resizeObserver.unobserve(element));
130+
};
131+
}
132+
return () => {};
122133
},
123134
[resizeObserver]
124135
);

0 commit comments

Comments
 (0)