Skip to content

Commit 2f94c17

Browse files
simon360Simon Andrews
authored andcommitted
docs: add details on rehydrateChildren and React.Fragment
1 parent 343d880 commit 2f94c17

File tree

1 file changed

+76
-3
lines changed

1 file changed

+76
-3
lines changed

docs/rehydrators/using-rehydratechildren.mdx

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,81 @@ The rehydrator should look like this:
2323
import ShowMore from "./ShowMore";
2424

2525
export default async (domNode, rehydrateChildren) => {
26-
const children = await rehydrateChildren(domNode.querySelector(".ShowMore-children"));
26+
const children = await rehydrateChildren(
27+
domNode.querySelector(".ShowMore-children")
28+
);
2729

2830
return <ShowMore>{children}</ShowMore>;
29-
}
30-
```
31+
};
32+
```
33+
34+
## `rehydrateChildren` and `React.Fragment`
35+
36+
If a component contains more than one child, then `rehydrateChildren` will return a `React.Fragment`. This may affect your components if you use `React.Children`, in order to iterate over child components from a parent component.
37+
38+
To overcome this, you have two options:
39+
40+
1. In your rehydrator function, you can check the type of the children you get back. If it's a `React.Fragment`, you can pass through its children. This isn't generally recommended, but it will work in a pinch.
41+
42+
```javascript
43+
(domNode, rehydrateChildren) => {
44+
const children = await rehydrateChildren(domNode.querySelector(".MyComponent-children"));
45+
46+
if (children.type === React.Fragment) {
47+
return <MyComponent>{children.props.children}</MyComponent>;
48+
}
49+
50+
return <MyComponent>{children}</MyComponent>
51+
}
52+
```
53+
54+
2. Unwrap `React.Fragment` while you iterate over children. This has the added advantage of making your component work with fragments, rather than patching support into the rehydrator.
55+
56+
```javascript
57+
const getTitles = children => {
58+
const titles = [];
59+
60+
React.Children.forEach(children, child => {
61+
if (child.type === React.Fragment) {
62+
// Recursively unwrap `React.Fragment`'s children, get their titles,
63+
// and add them to the return value.
64+
titles.push(...getTitles(child.props.children));
65+
} else if (child.type === MySubcomponent) {
66+
// For a specific component type, extract the title prop.
67+
titles.push(child.props.title);
68+
}
69+
});
70+
71+
return titles;
72+
};
73+
```
74+
75+
You could extend this to `cloneElement`, as well.
76+
77+
```javascript
78+
const getTitles = children => {
79+
const titles = [];
80+
81+
const mapCallback = child => {
82+
if (child.type === React.Fragment) {
83+
return (
84+
<React.Fragment>
85+
{React.Children.map(child.props.children, mapCallback)}
86+
</React.Fragment>
87+
);
88+
}
89+
90+
if (child.type === MySubcomponent) {
91+
return React.cloneElement(
92+
child,
93+
{ date: new Date() },
94+
child.props.children
95+
);
96+
}
97+
98+
return child;
99+
};
100+
101+
return React.Children.map(children, mapCallback);
102+
};
103+
```

0 commit comments

Comments
 (0)