どうも、イソップです。
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)
この記事の内容は全てドキュメントにあります
しっかりとドキュメント読みましょう。(自分に向けて)