November 25, 2020

複数のHOCでラップしたい時、composeを使えば読みやすい

Reactのコンポーネントを複数のHOC(High Order Components)でラップしてしまうと、ネストが深くなっていき、読み辛くなることがありますよね。いつも「あれ、どうするんだったっけ?」となってしまうので、ここにメモっておきます。

Updated at December 24, 2020

Reactのコンポーネントを複数のHOC(High Order Components)でラップしてしまうと、ネストが深くなっていき、読み辛くなることがありますよね。

いつも「あれ、どうするんだったっけ?」となってしまうので、ここにメモっておきます。


HOC(High Order Components)とは?

HOC(High Order Components)とは、他のコンポーネントをラップするReactコンポーネントのことです。

ラップされたコンポーネントを受け取り、新しいコンポーネントを返す関数ですね。

よく見かけるMaterial UIの例。

import React, { Component } from "react";
import { withStyles } from "@material-ui/core/styles";

const styles = {
  root: {
    color: `red`,
  },
};

class MyComponent extends Component {
  render() {
    return <div className={this.props.classes.root}>コンテンツ</div>;
  }
}

export default withStyles(styles)(MyComponent);

参考:
Higher-Order Components – React

これらのHOCを利用しているライブラリはよく見かけます。

複数のHOCでラップ

開発を進めていくと、こんな感じで複数のHOCでコンポーネントでラップする必要がでてきます。

import React, { Component } from 'react'
import { withRouter } from 'react-router-dom'
import { withStyles } from 'material-ui/styles'
import withWidth from 'material-ui/utils/withWidth'

class MyComponent extends Component {
  // ...
}

export default withRouter(withStyles(styles)(withWidth()(MyComponent)))

しかし、深くネストしていて、可読性が非常に低い…。

解決するには?

それを解決するには、recomposeライブラリの compose コンポーネントを使用します。

まずはパッケージをインストールしましょう。

コマンドライン
npm i recompose

先にあげた例を書き換えると、こんな感じ。

import React, { Component } from 'react'
import { withRouter } from 'react-router-dom'
import { withStyles } from 'material-ui/styles'
import withWidth from 'material-ui/utils/withWidth'
import compose from 'recompose/compose'

class MyComponent extends Component {
  // ...
}

export default compose(
  withRouter,
  withStyles(styles),
  withWidth()
)(MyComponent)

すっきり見やすくなりました✨

※上から順番に実行されます。

compose を使用することで、よりスマートに書くことが出来ますね。

高橋あゆみ

高橋あゆみ
フリーランスのUI/UXデザイナー。英語圏のロマンス・ミステリー小説にハマり、一向に減らない積読が悩み。カナダのバンクーバー在住。