<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: cieldon32</title>
    <description>The latest articles on DEV Community by cieldon32 (@cieldon32).</description>
    <link>https://dev.to/cieldon32</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F408697%2F8439daef-e7e1-43cd-a033-caea3c571b87.png</url>
      <title>DEV Community: cieldon32</title>
      <link>https://dev.to/cieldon32</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cieldon32"/>
    <language>en</language>
    <item>
      <title>How to use slots in react elegantly</title>
      <dc:creator>cieldon32</dc:creator>
      <pubDate>Sun, 28 May 2023 07:41:00 +0000</pubDate>
      <link>https://dev.to/cieldon32/how-to-use-slots-in-react-elegantly-5d2p</link>
      <guid>https://dev.to/cieldon32/how-to-use-slots-in-react-elegantly-5d2p</guid>
      <description>&lt;p&gt;We all know, we can use props to implement component slots. This is a good way, but the props of the components will become more and more.&lt;br&gt;
Also, you can filter the children by element's type, but it isn't a good idea.&lt;br&gt;
And, you can use HOC to wrap the Component, and use Proxy to reduce the children. you can use the subComponent, like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;YouComponent.SubComponentA&amp;gt;a&amp;lt;/YouComponent.SubComponentA&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then, your Component's props will get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;slot: {
   SubComponentA: {children, props}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a good idea. But There is a better way.&lt;br&gt;
We focus on children, children will be a array, or string, or a ReactElement, or undefined.&lt;br&gt;
The ReactElement has type, you can check the child with the type's name.&lt;br&gt;
You will use your Component like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;YouComponent&amp;gt;
    &amp;lt;Slot name="SubComponentA"&amp;gt;a&amp;lt;/Slot&amp;gt;
    b
&amp;lt;/YouComponent&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;&amp;lt;Slot /&amp;gt;&lt;/code&gt; is a component that it render null. And it has a generator function, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {ReactElement} from 'react'
import {SlotProps} from './slot.interface';

function Slot(_: SlotProps): ReactElement {
  return null as unknown as ReactElement;
}

Slot.getSlot = function* getCollectionNode(props: SlotProps): any {
  yield props.children;
};

let _Slot = Slot as (props: SlotProps) =&amp;gt; JSX.Element;
export default _Slot;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then, In your component's code, you can use a hook to reduce the children. The hook like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';

export function useSlot(children: any) {
  const result: Record&amp;lt;string, any&amp;gt; = {
    children: []
  };
  React.Children.map(children, (child: React.ReactElement&amp;lt;any, React.JSXElementConstructor&amp;lt;any&amp;gt;&amp;gt;) =&amp;gt; {
    if(React.isValidElement(child)){
      const type = child.type as any;
      const props = child.props;
      if(type.name === 'Slot') {
        const slot = type.getSlot(child.props);
        result[props.name] = slot.next().value;
      } else {
        result['children'].push(child);
      }
    } else {
      result['children'].push(child);
    }
  })
  return result;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the result of the useSlot(children), will be :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   SubComponentA: 'a',
   children: ['b']
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is my way to use slot in React. Do you have another way? Please tell me.&lt;/p&gt;

</description>
      <category>react</category>
      <category>slot</category>
    </item>
  </channel>
</rss>
