Skip to content

Commit a8a926e

Browse files
dmgawelPrincesseuh
andauthored
fix(react): Fix empty conditional slots hydration issues (#15378)
* fix(react): Fix empty conditional slots hydration issues * add changeset * typo in changeset * Update nine-lights-rest.md --------- Co-authored-by: Erika <3019731+Princesseuh@users.noreply.github.com>
1 parent f771f75 commit a8a926e

File tree

5 files changed

+46
-1
lines changed

5 files changed

+46
-1
lines changed

.changeset/nine-lights-rest.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@astrojs/react': patch
3+
---
4+
5+
Fix React hydration errors when using conditional slot rendering

packages/integrations/react/src/static-html.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ const StaticHtml = ({
1616
name?: string;
1717
hydrate?: boolean;
1818
}) => {
19-
if (!value) return null;
19+
// value can be a SlotString object, we need to check if it's empty by using trim()
20+
if (value == null || value.trim() === '') return null;
2021
const tagName = hydrate ? 'astro-slot' : 'astro-static-slot';
2122
return h(tagName, {
2223
name,
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import React from 'react';
2+
3+
export default function ({ id, conditional = null }) {
4+
return (
5+
<div id={id}>
6+
<div className="conditional-slot">{conditional}</div>
7+
</div>
8+
);
9+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
import ConditionalSlot from '../components/ConditionalSlot.jsx';
3+
4+
const showEmptySlot = false;
5+
const showFilledSlot = true;
6+
---
7+
8+
<html>
9+
<head>
10+
<title>Slots</title>
11+
</head>
12+
<body>
13+
<ConditionalSlot id="empty" client:load>
14+
{showEmptySlot ? <span slot="conditional">Hidden</span> : null}
15+
</ConditionalSlot>
16+
17+
<ConditionalSlot id="filled" client:load>
18+
{showFilledSlot ? <span slot="conditional">Visible</span> : null}
19+
</ConditionalSlot>
20+
</body>
21+
</html>

packages/integrations/react/test/react-component.test.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,15 @@ describe('React Components', () => {
130130
assert.equal($('#three .title').text(), 'Hello');
131131
assert.equal($('#three .subtitle').text(), 'World');
132132
});
133+
134+
it('Does not render astro-slot for empty slots', async () => {
135+
const html = await fixture.readFile('/slots/index.html');
136+
const $ = cheerioLoad(html);
137+
138+
assert.equal($('#empty astro-slot[name="conditional"]').length, 0);
139+
assert.equal($('#filled astro-slot[name="conditional"]').length, 1);
140+
assert.equal($('#filled astro-slot[name="conditional"]').text().trim(), 'Visible');
141+
});
133142
});
134143

135144
if (isWindows) return;

0 commit comments

Comments
 (0)