I'm building a UI library with React. We use the Children API and some child.type checks to filter specific children, like this for example:
const listItems = React.Children.map(children, (child) => {
if (React.isValidElement(child) && child.type === ListItem) {
return React.cloneElement(child);
}
});
This works fine in Client Components, but users report that it breaks in React Server Components. The comparison child.type === ListItem fails, likely due to differences in module resolution between server and client.
I know that the Children API is somewhat legacy and switching to render props might be the better long-term solution, but that would require breaking changes across many components.
Question:
Is there a way to fix the child.type comparison so it works inside a React Server Component? Or is switching to a different pattern the only viable solution?
Any insights would be appreciated!
Edit: child
looks like this:
I'm building a UI library with React. We use the Children API and some child.type checks to filter specific children, like this for example:
const listItems = React.Children.map(children, (child) => {
if (React.isValidElement(child) && child.type === ListItem) {
return React.cloneElement(child);
}
});
This works fine in Client Components, but users report that it breaks in React Server Components. The comparison child.type === ListItem fails, likely due to differences in module resolution between server and client.
I know that the Children API is somewhat legacy and switching to render props might be the better long-term solution, but that would require breaking changes across many components.
Question:
Is there a way to fix the child.type comparison so it works inside a React Server Component? Or is switching to a different pattern the only viable solution?
Any insights would be appreciated!
Edit: child
looks like this:
You could put some unique identifier on ListItem and check for that. For example:
const ListItem = (props) => {
// ...
}
ListItem.isListItem = true;
const listItems = React.Children.map(children, (child) => {
if (
React.isValidElement(child) &&
typeof child.type === "function" &&
child.type.isListItem === true
) {
return React.cloneElement(child);
}
});