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

Your email address will not be published. Required fields are marked *