はじめに
React の高階コンポーネントのメモです。
ご指摘、感想、お待ちしています。。。
目次
- 高階コンポーネント???
- まずは普通に書いてみる
- 高階コンポーネントを作成
- 高階コンポーネントをくっ付ける
- まとめ
1. 高階コンポーネント???
高階コンポーネントとは。。。
公式の Docs
以下は、引用です。
高階コンポーネント (higher-order component; HOC) はコンポーネントのロジックを再利用するための
React における応用テクニックです。HOC それ自体は React の API の一部ではありません。
HOC は、React のコンポジションの性質から生まれる設計パターンです。
さらにさらに。
具体的には、高階コンポーネントとは、あるコンポーネントを受け取って新規のコンポーネントを返すような関数です。
ほうほう、どうやらコンポーネントのロジックを再利用(=使い回す)ためのテクニックなのか。。
では、実際に書いてみよう。
2. まずは普通に書いてみる
簡単なカウンターのコンポーネントを 2 つ用意します。
カウントの条件は以下
- ボタンのクリック
- マウスでホバー
import React, { Component } from "react";
class ClickCounter extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
incrementCount = () => {
this.setState(prevState => {
return { count: prevState.count + 1 };
});
};
render() {
return (
<div>
<button onClick={this.incrementCount}>
clicked {this.state.count} times
</button>
</div>
);
}
}
export default UpdatedComponent(ClickCounter);
import React, { Component } from "react";
class HoverCounter extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
incrementCount = () => {
this.setState(prevState => {
return { count: prevState.count + 1 };
});
};
render() {
return (
<div>
<h3 onMouseOver={this.incrementCount}>
Hover {this.state.count} times
</h3>
</div>
);
}
}
export default HoverCounter;
ここで、各コンポーネントで共通の箇所は以下の部分です。
constructor(props) {
super(props)
this.state = {
count: 0
}
}
incrementCount = () => {
this.setState(prevState => {
return { count: prevState.count + 1 }
})
}
3. 高階コンポーネントを作成
冒頭の引用にあるように
あるコンポーネントを受け取って新規のコンポーネントを返すような関数です。
高階コンポーネントを作成しましょう。
- 高階コンポーネント :
higherOrderComponent
- 受け取るコンポーネント :
OriginalComponent
- 新規のコンポーネント :
NewComponent
NewComponent
で共通箇所として注目した
count
- インクリメントに必要な
incrementCount
を定義しています。
それらを、OriginalComponent
のpropsとして持たせてあげます。
import React from 'react'
const higherOrderComponent = OriginalComponent => {
class NewComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
}
incrementCount = () => {
this.setState(prevState => {
return { count: prevState.count + 1 }
})
}
render() {
return <OriginalComponent count={this.state.count} incrementCount={this.incrementCount}/>
}
}
return NewComponent
}
export default higherOrderComponent
4. 高階コンポーネントをくっ付ける
高階コンポーネントを利用してみましょう。
higherOrderComponent(ClickCounter)
の箇所で利用がされています。
そうすると、count
やincrementCount
は高階コンポーネントがpropsで渡してくれているので
各コンポーネントで定義やロジックの実装が不要になります。
import React, { Component } from 'react'
import higherOrderComponent from './Counter'
class ClickCounter extends Component {
render() {
return (
<div>
<button onClick={this.props.incrementCount}>clicked {this.props.count} times</button>
</div>
)
}
}
export default higherOrderComponent(ClickCounter)
import React, { Component } from 'react'
import higherOrderComponent from './Counter'
class HoverCounter extends Component {
render() {
return (
<div>
<h3 onMouseOver={this.props.incrementCount}>Hover {this.props.count} times</h3>
</div>
)
}
}
export default higherOrderComponent(HoverCounter)
5. まとめ
高階コンポーネントを利用して、コンポーネントのロジックを共通化できました。
めでたし、めでたし。
おしまい。