react-templated
v1.0.1
Published
Yet another implementation of slot components for React
Downloads
4
Readme
react-templated
Yet another implementation of slot components for React. It's inspired by WebComponents slots.
full documentation can be found on https://andres-kovalev.github.io/react-templated/
Description
react-templated
provides several components to created templated components.
Installation
As any other npm package react-templated
can be added to your project by following command:
npm i -S react-templated
It requires any version of react with new context API support as peer dependency, so it should be installed as well.
npm i -S react
Quick start
By default content for React component can be accessed by children
prop:
function Parent() {
return (
<Child>
<div>our div 1</div>
<div>our div 2</div>
</Child>
);
}
...
function Child(props) {
// here are our divs
const { children } = props;
...
}
But some times we need to distribute children between different areas of our component. We might want to create a template. We can extract try to extract separate children and use those:
function Child({ children }) {
const [ child1, child2 ] = children.props.children;
return (
<React.Fragment>
<div className="header">
{child1}
</div>
<div className="body">
{child2}
</div>
</React.Fragment>
);
}
Looks a bit ugly. Also, we need to provide some safe-checks/fallbacks to prevent issues when user provides less than 2 children and we need to find some way to be able to provide only 2nd/3rd/etc item.
import _ from 'lodash';
function Child({ children }) {
const [ child1, child2 ] = _.get(children, 'props.children', []);
...
}
function Parent() {
return (
<React.Fragment />
<div>body</div>
);
}
Another way is to use different props for different areas:
const Page = ({ header, body, footer }) => (
<div className="page">
<div className="header">
{ header }
</div>
<div className="body">
{ body }
</div>
<div className="header">
{ footer }
</div>
</div>
)
Looks much better, but it's still not so convenient to use such components and provide default content:
const App = () => (
<Page
header={ <Header /> }
body={ <Body /> }
footer={ <Footer /> }
/>
);
// or
const App = () => {
const header = <Header />;
const body = <Body />;
const footer = <Footer />;
const props = { header, body, footer };
return <Page { ...props } />;
}
One more option is to use slots from react-templated
package. First we need to create our template:
import { Slot, withSlots, Value } from 'react-templated';
// it's not necessary to provide any props for template
const PageTemplate = () => (
<div className="page">
<div className="header">
<Slot name="header">
Slot content will be found by slot name
We can provide default content for the slot here
</Slot>
</div>
<div className="body">
<Slot>
We can skip name to mark slot as default
</Slot>
</div>
<div className="header">
<Slot name="footer" />
{/* it's not necessary to provide default content */}
</div>
</div>
);
The next step is to enhance our component with slot power:
const Page = withSlots(PageTemplate);
Now we can provide any content for Page
component and it will be distributed automatically:
const App = () => (
<Page>
<Value name="header">
Header content
</Value>
<Value name="footer">
Footer content
</Value>
Everything else will be considered as default content
and will appear in default slot
</Page>
);
That's it. For those, who don't like HoCs react-templated
provides Templated
wrapper:
import { Templated } from 'react-templated';
const Page = ({ children }) => (
<Templated content={ children }>
<PageTemplate />
<Templated>
);
The code abowe is equivalent to withSlots()
HoC.