react-css-modulesで、子コンポーネントにstyleNameのスタイルを適用する

スポンサーリンク

どうも、イソップです。

ReactでのCSS modules適用を拡張するモジュールの、react-css-modulesがありますが、
コンポーネントの中で定義した子コンポーネントをrenderする場合、styleName がうまく動作しなかったので備忘録を残しておきます。

CSSModules()は子コンポーネント以下には影響しない

次のコードでは、CustomListコンポーネントのrenderメソッドの中で、
itemTemplate を定義しています。これが子コンポーネント

List を介しているので、 itemTemplateに当たります。

import React from 'react';
import CSSModules from 'react-css-modules';
import List from './List';
import styles from './table.css';

class CustomList extends React.Component {
    render () {
        let itemTemplate;

        itemTemplate = (name) => {
            return <li styleName='item-template'>{name}</li>;
        };

        return <List itemTemplate={itemTemplate} />;
    }
}

export default CSSModules(CustomList, styles);

※GithubのREADMEからコード抜粋

これでは上手くいきませんでした。
CSSModules()が適用されるのはCustomListコンポーネント自身で、
renderで返るのは List コンポーネントだからです。

this.props.stylesを子コンポーネントに渡す

itemTemplate の中にある li タグのclassNameに、CustomList.props.styles に該当のキーを指定して渡します。

import React from 'react';
import CSSModules from 'react-css-modules';
import List from './List';
import styles from './table.css';

class CustomList extends React.Component {
    render () {
        let itemTemplate;

        itemTemplate = (name) => {
            return <li className={this.props.styles['item-template']}>{name}</li>;
        };

        return <List itemTemplate={itemTemplate} />;
    }
}

export default CSSModules(CustomList, styles);

styleNameを使わず、ちょっと長ったらしい感じです。
これなら上手くスタイルが適用されます。

CSSModules()を使う

import React from 'react';
import CSSModules from 'react-css-modules';
import List from './List';
import styles from './table.css';

class CustomList extends React.Component {
    render () {
        let itemTemplate;

        itemTemplate = (name) => {
            return <li styleName='item-template'>{name}</li>;
        };

        itemTemplate = CSSModules(itemTemplate, this.props.styles);

        return <List itemTemplate={itemTemplate} />;
    }
}

export default CSSModules(CustomList, styles);

READMEには CSSModules() をコンポーネントの中でも実行するやり方が記載されていましたが、
孫ではなく子に適用したい場合、動作しませんでした

一応コードを載せておきます。

ぼくとしては、動かないのがすごい気持ち悪いし、こっちのほうがスマート実装なので、引き続き原因を調査したいと思います。

デバッグ用にクラス名を整形する

CSSモジュールを利用すると、出力されるクラス名は class="_9es73jfjdksa7zxd" のようにランダムな文字列になります。
これではCSSのデバッグが難しいので、次のようにwebpackのloader設定を変更することで、わかりやすいクラス名に整形することができます。

CSS

{
  test: /\.css$/,
  loaders: [
    'style?sourceMap',
    'css?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]'
  ]
}

SCSS

{
  test: /\.scss$/,
  loaders: [
    "style",
    "css?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]",
    "sass"
  ]
}

上記の設定では、src-components-Button-___button-icon___fj3kQ のように出力されます。

ちなみに、webpackで使用できるパス変数はざっとこんな感じです。

[name]
[local]
[path]
[hash:base64:5]
[folder](parent dir name)
[ext](file extension)
[emoji:XXXX](emoji by codepoint)

この記事の内容は全てドキュメントにあります

しっかりとドキュメント読みましょう。(自分に向けて)


イソップへのお悩み相談募集中

イソップに相談しませんか?

当ブログで紹介しているような、Web制作やフリーランスへの悩みをイソップに相談してみませんか?
回答できることがあれば記事の中でご紹介します。