• Pass Multiple Children to a React Component with Slots
  • Written by Dave Ceddia
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: Zheng7426
  • Proofreader: Noahziheng, BillShiyaoZhang

Let’s say you need to write a reusable component. But prop, called Children, doesn’t answer that need. The component has to be able to receive more than one child, and the children are not placed next to each other, but on demand.

Maybe you’re writing a component called Layout with a title, a sidebar, and a content block. Or maybe you happen to be writing a NavBar component with a dynamic left and right sidebar.

All of these tasks can be easily done in “slot” mode, in other words, passing JSX into a prop.

Summary: You can pass JSX to any prop not just called Children, and not just by embedding JSX in a component’s tag — simplifying data transfer while making the component more reusable.

A quick review of Children in React

Let’s start with the fact that React lets you pass children to components by nesting them between JSX tags. These elements (zero, one, or more) will exist in that component as a prop named Children. React’s Prop called Children is the equivalent of Angular Transclusion and Vue’s

.

Here is an example of passing children to a Button component:

<Button>
  <Icon name="dollars"/>
  <span>BUY NOW</span>
</Button>
Copy the code

Let’s take a closer look at the Button component implementation and see what it does to children:

function Button(props) {
    return (
    <button>
        {props.children}
    </button>
    );
}
Copy the code

Button effectively encapsulates your prequel in a Button element. There is nothing earth-shattering about getting to this point, but it is a practical ability. It allows The receiving component to place children anywhere in The layout or encapsulate them in a The className for changing The style. The rendered HTML code would look something like this:

<button>
    <i class="fa fa-dollars"></i>
    <span>BUY NOW</span>
</button>
Copy the code

(Incidentally, let’s assume that the Icon component renders the < I > tag.)

Children is also a generic Prop

React’s use of children is cool: nested elements can specify a prop named Children, but this isn’t a magical or special prop. You can specify any other element to a prop. And look:

<Button children={<span>Click Me</span>} /> / <Button> <span>Click Me</span> </Button>Copy the code

So not only can you pass children like a normal prop, you can also pass JSX code inside prop. Are you surprised? True, this feature isn’t exclusive to prop called “Children”!

Use Props for named card slots

What if I told you that you could pass JSX code to any prop?

(You already know the secret, don’t you?) Here is an example of props using these “card slots” — calling a component named Layout with three props:

<Layout
  left={<Sidebar/>}
  top={<NavBar/>}
  center={<Content/>}
/>
Copy the code

In this component called Layout, it can use the left, top, and Center props as it wishes. Here’s a simple example:

function Layout(props) {
  return (
    <div className="layout">
      <div className="top">{props.top}</div>
      <div className="left">{props.left}</div>
      <div className="center">{props.center}</div>
    </div>
  );
}
Copy the code

Imagine that the code inside a Layout component can become very complex, with many nested div or Bootstrap class names, and so on. This component can also pass information to more detailed components. Whatever Layout needs to do, its users just need to know how to pass three prop left, top, and Center.

Use Children to pass Props directly

Another nice feature about passing children (regardless of whether the prop is children or not) is that when you pass a Child prop, which is in the parent’s scope, you can pass down whatever information you want.

It’s like skipping a level. For example, instead of passing a “user” to a Layout and having a Layout pass the “user” to a NavBar component, create a NavBar (with the user set) and pass the entire NavBar to a Layout. This helps avoid the problem of “prop drilling”, where you don’t have to bother putting a prop into a hierarchy of multiple components.

function App({ user }) {
  return (
    <div className="app">
      <Nav>
        <UserAvatar user={user} size="small"/> </Nav> <Body sidebar={<UserStats user={user} />} content={<Content />} /> </div> ); } // Take children and render it const Nav = ({children}) => (<div className="nav"> {children} </div> ); Const Body = ({sidebar, content}) => (<div className=) const Body = ({sidebar, content}) ="body">
    <Sidebar>{sidebar}</Sidebar>
    {content}
  </div>
);

const Sidebar = ({ children }) => (
  <div className="sidebar">
    {children}
  </div>
);

const Content = () => (
  <div className="content">main content here</div>
);
Copy the code

Now compare this to the following, where Nav and Body both accept a prop named User and are then responsible for manually passing the prop to children. After that, their children must be passed on to the children of a finer layer…

function App({ user }) {
  return (
    <div className="app">
      <Nav user={user} />
      <Body user={user} />
    </div>
  );
}

const Content = () => <div className="content">main content here</div>;

const Sidebar = ({ user }) => (
  <div className="sidebar">
    <UserStats user={user} />
  </div>
);

const Body = ({ user }) => (
  <div className="body">
    <Sidebar user={user} />
    <Content user={user} />
  </div>
);

const Nav = ({ user }) => (
  <div className="nav">
    <UserAvatar user={user} size="small" />
  </div>
);
Copy the code

It’s not as convenient as the previous one, right? Passing a prop down this way (aka “prop drilling”) can get the components into a lot of trouble with each other that you probably don’t want — not always a bad thing, but you’d better figure out how they’re all connected. The first way above, using children, avoids the need for more complex solutions, such as using context, Redux, or MobX (among many others).

Beware PureComponent or shouldComponentUpdate

If you need to implement shouldComponentUpdate (or PureComponent) on a component with children, this prevents second rendering and children cannot be rendered. So pay attention to that. In practice, components with “slots” are likely to be small and render fast, so they won’t require performance tweaks.

However, if you have a situation where you really need to adjust the performance of a “slot” component, consider pulling out the parts of the code that are performing too slowly, putting them in a separate component, and then adjusting them.

Learning React can be a pain at times — there are so many code libraries and tools! You want my opinion? Ignore all the code libraries and tools 🙂 if you want a step-by-step guide, read my book Pure React.

If you find any mistakes in your translation or other areas that need to be improved, you are welcome to the Nuggets Translation Program to revise and PR your translation, and you can also get the corresponding reward points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.