この記事で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-motionやreact-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"));