I would like to share here a method, which I use for children passing to ‘slots’.
Say, for example, you need to develop menu with different backgrounds for menu items:
<div class="my-menu-parent"> <div class="my-menu-item-red"> <a href="#"><img src="http://fullhdwall.com/wp-content/uploads/2016/09/Best-World.jpg" /></a> </div> <div class="my-menu-item-yellow"> <span>My second menu item</span> </div> <div class="my-menu-item-blue"> <span>My Blue menu item</span> </div> </div
To use React, one should to devide this to components. I would do it like that:
<Menu>
<MenuItem position="menu-item-red">
{/*here goes custom content for red item*/}
<MenuItem />
<MenuItem position="menu-item-yellow">
{/*here goes custom content for yellow item*/}
<MenuItem />
<MenuItem position="menu-item-blue">
{/*here goes custom content for blue item*/}
<MenuItem />
</ Menu>
import React from 'react';
import PropTypes from 'prop-types';
const Menu = (props) => {
// our slots
const positions = ['my-menu-item-red', 'my-menu-item-yellow', 'my-menu-item-blue'];
const groupedChildren = React.Children
.toArray(props.children)
.reduce((result, child) => {
const position = child.props.position;
if (positions.some(el => el === position)) {
return {
...result,
[position]: result[position] ? result[position].concat(child) : [child]
};
}
return result;
},
{});
return (
<div className="menu">
{positions.map((position, index) => (
<div key={index} className={position}>
{groupedChildren[position]}
</div>)
)}
</div>
);
};
Menu.propTypes = {
children: PropTypes.node.isRequired,
};
export default Menu;
And MenuItem contains any markup for grouping menu items in blue, yellow or red groups and outputs any custom content provided to it:
import React from 'react';
import PropTypes from 'prop-types';
const MenuItem = (props) =>
<div>{ props.children }</div>;
MenuItem.propTypes = {
children: PropTypes.any.isRequired
};
export default MenuItem;
So the final usage of there components will be like that:
<Menu>
<MenuItem position="menu-item-red">
{/*here goes custom content for first item*/}
<MenuItem />
<MenuItem position="menu-item-yellow">
{/*here goes custom content for second item*/}
<MenuItem />
<MenuItem position="menu-item-blue">
{/*here goes custom content for third item*/}
<MenuItem />
</ Menu>
Leave a Reply