この記事でReactコンポーネントのchildrenにFunctionを渡していて気になったが、childrenとしてFunctionを渡すパターンがあるらしい

コード

  • propsのchildrenを関数呼び出しするのがポイント
    • TypeScriptで単純にthis.props.childrenを関数呼び出しすると型定義でエラーになった
import * as React from "react";
import * as ReactDOM from "react-dom";

class Container extends React.Component<{}, {}> {
    render(){
        const children = this.props.children as Function;
        return <div>
            {children({foo: "bar"})} // propsのchildrenを関数呼び出し
        </div>
    }
}

class App extends React.Component<{}, {}> {
    render(){
        return <Container>
            {({foo}) => <div>Content {foo}</div>}
        </Container>
    }
}

ReactDOM.render(<App/>, document.getElementById("root"));

何に使えるか

  • このパターンがreact-motionreact-measure等で利用されてるのを見ると、レンダリングに関する複雑な処理をコンポーネントに押し込め、かつ、その処理結果に基づいてchildrenを描画したい場合に使えそうだ
  • こちらでは、propsで渡したurlからfetchした結果に基づいて、childrenを描画するコンポーネントの例が示されているので、このような非同期処理等に係るstateの変化をコンポーネントに押し込めるのにも使えそう

例:タイマーコンポーネント

すごく人工的な例…
一定時間置きに時間更新するという処理をコンポーネントに押し込め、具体的な描画はchildrenコンポーネントでやる

import * as React from "react";
import * as ReactDOM from "react-dom";

class Timer extends React.Component<{ interval: number }, {}> {
    private timer = null;
    state = {
        now: new Date()
    };

    onTimer = () => {
        this.setState({ now: new Date() });
        this.timer = setTimeout(this.onTimer, this.props.interval);
    };

    componentWillMount() {
        this.onTimer();
    }

    componentWillUnmount() {
        clearTimeout(this.timer);
    }

    render() {
        const children = this.props.children as Function;
        return children({ ...this.state, ...this.props });
    }
}

class App extends React.Component<{}, {}> {
    render() {
        return <Timer interval={1000}>
            {({ now }) => <div>Timer {now.toLocaleTimeString()}</div>}
        </Timer>
    }
}

ReactDOM.render(<App />, document.getElementById("root"));

参考文献

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.