From the blog

Elegant React Component APIs with Functions as Children

react

We can develop some pretty elegant React Component APIs using functions as children in React Components. Take for example a Dropdown component. If we want it to be flexible by leaving the DOM structure up to the user, we would need some way to designate toggler elements of the Dropdown. One way is with the data-toggle attribute:

Open

However, this will require manually setting up event listeners on real DOM nodes, for example, the componentDidMount method on this component might look something like this:

componentDidMount() {
  const togglers = ReactDOM
    .findDOMNode(this)
    .querySelectorAll('[data-toggle]');
  Array.prototype.forEach.call(togglers, toggler => {
    toggler.addEventListener('click', this.toggle);
  });
},

A more elegant solution is to expose the component’s toggle method to its children by using a function as a child:

  {toggle =>

Open

 

}


This way, we’re using React’s event system instead of raw DOM events, and we wouldn’t need to implement componentDidMount at all.
When toggle is called, the opened CSS class will be toggled on the div element. In other words, the component would generate DOM that looks like this:

 

and when the toggle function is called, the opened class is added to the element:

 

The implementation of this Dropdown component looks like this:

const cx = require('classnames');
const enhanceWithClickOutside = require('react-click-outside');
const React = require('react');
const Dropdown = React.createClass({
  getInitialState() {
    return {
      opened: false,
    };
  },
  handleClick(e) {
    // Close dropdown when clicked on a menu item
    if (this.state.opened && e.target.tagName === 'A') {
      this.setState({ opened: false });
    }
  },
  handleClickOutside(e) {
    if (!this.state.opened) return;
    this.setState({ opened: false });
  },
  toggle() {
    this.setState({ opened: !this.state.opened });
  },
  render() {
    const child = this.props.children(this.toggle);
    return React.cloneElement(child, {
      className: cx(
        child.props.className,
        'dropdown',
        this.state.opened && 'opened'
      ),
      onClick: this.handleClick,
    });
  },
});
module.exports = enhanceWithClickOutside(Dropdown);

this.props.children is the function child of the Dropdown component, and it is called with the instance’s toggle method. This returns a React Element, the div, which we clone to add the dropdown and opened css classes.
A discussion of this pattern and other real world use cases can be found here.

Related articles

In-Browser SSH(ブラウザー上でのセキュアシェル)の紹介:クラスターノードへの最速のアクセス方法

RescaleのアプリケーションエンジニアであるAlex Huangがポストしたブログ記事の翻訳です。 Alex Huang – 2017年2月20日 このたびRescaleは、当社のプラットフォームで利用可能な強力な新機能、In-Browser SSH(ブラウザー上でのセキュアシェル)を導入しました。Linuxをサポートしているプロバイダーのコンピューティングクラスターを使用するジョブであれば、Live Tailigパネル(テールパネル)の下に実行中のクラスターに接続するためのSSHパネルが表示され、SSHを利用できます。

read more »

Manor Racing Partners with Rescale Cloud HPC For Trackside Simulation Advantage

San Francisco, CA – Manor Racing is partnering with San Francisco based Rescale as a key technology provider for its 2016 FIA Formula 1 World Championship challenge. Manor Racing will use Rescale’s cloud high performance computing (HPC) platform to enable […]

read more »