This is a set of components which provide a similar and familiar implementation of the HTML5 <slot>
behavior for react. Please note, this does not use real slots under the hood, but rather provides developers with the same expressive experience.
Check out the demo!
npm install react-slots
yarn add react-slots
- Use the
Slot
component like you would normal<slot>
elements. - Pass your component to the
SlotHost
function (HOC).
import React from "react";
import { SlotHost, Slot } from "react-slots";
const PageLayout = (props) => {
return (
<div className="page-layout" {...props}>
<header>
<Slot name="header">Default header</Slot>
</header>
<div className="content">
<main>
<Slot /> {/* Same as <Slot name="default" /> */}
</main>
<aside>
<Slot name="aside">Default aside</Slot>
</aside>
</div>
<footer>
<Slot name="footer">Default footer</Slot>
</footer>
</div>
);
};
export default SlotHost(PageLayout);
- Fill the slots with your content by adding the "slot" attribute to top-level elements and components.
<PageLayout>
<span slot="header">Logo and top navigation</span>
<p>All other content will be placed into the "default" (or unnamed) slot</p>
<div slot="aside">Side nav and advertisements</div>
<SomeComponent slot="footer">Footer nav and contact info</SomeComponent>
</PageLayout>
-
Any component which uses slots must be wrapped in the
SlotHost
HOC.const SimpleButton = (props) => { return ( <button {...props}> <Slot /> </button> ); }; export default SlotHost(SimpleButton);
-
This is analogous to the HTML5
<slot>
element - the "name" is optional. Any slot without a name becomes the "default" slot (same as<Slot name="default" />
). If the user does not provide any content, thefallback
content will be used.NOTE: see Advanced Usage below for other neat features
-
This is a utility component which will only render its children in the given slot. This is best explained by example:
// Without a Template: <SomeComponent> <span slot="foo">The span gets inserted into the slot</span> </SomeComponent> // With a Template: <SomeComponent> <Template slot="foo">Only the text gets inserted into the slot</Template> </SomeComponent>
-
This is a utility component for conditionally rendering content depending on whether the slot as assigned any content.
const SomeComponent = () => { return ( <div> <Slot name="header" /> <IfSlotAssigned name="footer"> {/* This will only render if the "footer" slot is used */} <footer> <Slot name="footer" /> </footer> </IfSlotAssigned> </div> ); };
You can pass custom data to slots by doing the following:
const PageLayout = () => {
// This is just an example - you have to get the data yourself
const currentUser = getCurrentUser();
return (
<div>
<Slot name="header" foo="bar" currentUser={currentUser} />
<Slot />
<Slot name="footer" bing="baz" currentUser={currentUser} />
</div>
);
};
Then you can use a "render prop" to access the data:
<PageLayout>
<header slot="header">
{({ currentUser, foo }) => {
return (
<div>
Hello {currentUser.name}! The FOO is {foo}.
</div>
);
}}
</header>
...
<footer slot="footer">
{({ currentUser, bing }) => {
return (
<div>
Hello {currentUser.name}! The BING is {bing}.
</div>
);
}}
</footer>
</PageLayout>