LoginSignup
7
2

More than 3 years have passed since last update.

Reactの高階コンポーネントのメモ

Posted at

はじめに

React の高階コンポーネントのメモです。
ご指摘、感想、お待ちしています。。。

目次

  1. 高階コンポーネント???
  2. まずは普通に書いてみる
  3. 高階コンポーネントを作成
  4. 高階コンポーネントをくっ付ける
  5. まとめ

1. 高階コンポーネント???

高階コンポーネントとは。。。
公式の Docs
以下は、引用です。

高階コンポーネント (higher-order component; HOC) はコンポーネントのロジックを再利用するための
React における応用テクニックです。HOC それ自体は React の API の一部ではありません。
HOC は、React のコンポジションの性質から生まれる設計パターンです。

さらにさらに。

具体的には、高階コンポーネントとは、あるコンポーネントを受け取って新規のコンポーネントを返すような関数です。

ほうほう、どうやらコンポーネントのロジックを再利用(=使い回す)ためのテクニックなのか。。
では、実際に書いてみよう。

2. まずは普通に書いてみる

簡単なカウンターのコンポーネントを 2 つ用意します。
カウントの条件は以下

  • ボタンのクリック
  • マウスでホバー
ClickCounter
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);
HoverCounter
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として持たせてあげます。

higherOrderComponent
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)の箇所で利用がされています。
そうすると、countincrementCountは高階コンポーネントがpropsで渡してくれているので
各コンポーネントで定義やロジックの実装が不要になります。

ClickCounter
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)
HoverCounter
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. まとめ

高階コンポーネントを利用して、コンポーネントのロジックを共通化できました。
めでたし、めでたし。
おしまい。

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2