Last active
December 7, 2022 14:50
-
-
Save granmoe/274c299b792b039deecfb619753ea32c to your computer and use it in GitHub Desktop.
Ever wanted to join react children like you join an array?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file is only here to provide the title of the gist |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react' | |
import joinChildren from 'react-join-children' | |
import { Item, Separator } from 'justanexample' | |
export default class MyComponent extends React.Component { | |
render () { | |
return <div> | |
{ joinChildren(this.props.items, this.renderItem, this.renderSeparator) } | |
</div> | |
// with 3 items, joinChildren returns [<Item>, <Separator>, <Item>, <Separator>, <Item>] | |
} | |
renderItem = (item, index) => { | |
return <Item key={ index } className="item" /> | |
} | |
renderSeparator = key => { | |
return <Separator className="separator" key={ key } /> | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default function (children, render, renderSeparator) { | |
return children.reduce((result, child, index) => { | |
if (index < children.length - 1) { | |
return result.concat([render(child, index), renderSeparator(index + '-separator')]) | |
} | |
return result.concat(render(child, index)) | |
}, []) | |
} |
@granmoe you need to assign a key prop to the fragments:
{list.map((item, index) => (
<React.Fragment key={item.id}>
{!!index && <Separator />}
<Item item={item} />
</React.Fragment>
))}
@granmoe you need to assign a key prop to the fragments:
{list.map((item, index) => ( <React.Fragment key={item.id}> {!!index && <Separator />} <Item item={item} /> </React.Fragment> ))}
Yep, good catch.
(This was just a hastily written example, but may as well not encourage poor practices 👍)
import React, { FunctionComponent, ReactNode } from 'react';
export const Separated: FunctionComponent<{ separator?: ReactNode }> = ({ children, separator = ' ' }) => {
return (
<>
{React.Children.toArray(children)
.reduce<ReactNode[]>((previousValue, currentValue) => {
return [...previousValue, currentValue, separator];
}, [])
.slice(0, -1)}
</>
);
};
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
So, some years have passed, and now we have React fragments, which don't add any extra nodes to the DOM, so we can simply do:
This is similar to @dinzy17's approach above, but it doesn't add an extra wrapper around each item (just for cases where you don't or can't add an extra wrapper).