これは「コードを書いていて困ったときに、suinがチャットで質問に答えたり相談に乗るsuinのプログラミング相談室(仮)」で頂いた質問と僕の回答の要約です。
質問
Reactで同じコンポーネントに違うスタイルを当てるにはどのようにしたらいいですか? ABテストを考えていて、ある条件ではスタイルAを、別の条件ではスタイルBを当てられるようにしたいです。
suinの回答
CSSで解決する方法と、Reactで解決する方法の2つが考えられます。
CSSで解決する方法
例えば、ReactのAppモジュールではapp
クラスを決め打ちにしておいて、ReactがレンダリングされるDOMをclass="red"
やclass="blue"
で囲めば、.red .app
、.blue .app
でそれぞれ別のスタイルが適用できます。React外の技術でアプローチするパターンですね。
<div class="red">
<div id="root"></div>
</div>
<div class="blue">
<div id="root"></div>
</div>
class App extends React.Component {
render () {
return <div className="app">App!</div>
}
}
ReactDOM.render(<App />, document.getElementById('root'))
.red .app {
color: red;
}
.blue .app {
color: blue;
}
Reactで解決する方法
Reactでやる場合は、コンポーネントの設定値をコンポーネント使う側から渡せるようにします。
class App extends React.Component {
// 属性情報のバリデーション
static propTypes = {
taste: React.PropTypes.string.isRequired
}
// 親からXML属性で受け取れるようにする
constructor (props) {
super(props)
this.state = {...なにかあれば...}
}
render () {
console.log(this.props) // ここで taste 属性があるはず
// ここでスタイルを切り替える
const className = this.props.taste === 'red' ? 'red-app' : 'blue-app'
// たしかこれでいいはず
return <div className={className}>App!</div>
}
}
// コンポーネントを使う側
ReactDOM.render(<App taste="red" />, document.getElementById('red-app'))
ReactDOM.render(<App taste="blue" />, document.getElementById('blue-app'))
<div id="red-app"></div>
<div id="blue-app"></div>
.red-app {
color: red;
}
.blue-app {
color: blue;
}
PHP(サーバサイド)側で動的にスタイルを指定する場合
ちなみに、サーバサイドでスタイルを動的に指定する場合はこうです。まず、PHP側では動的にdata-taste
を書き出すようにします。
<?php
$taste = $someCondition ? 'red' : 'blue';
echo '<div id="app" data-taste="' . $taste . '"></div>';
サーバサイドのロジックによって
<div id="app" data-taste="red"></div>
などが描画されます。
JSではそれを受け取れるようにします。
const element = document.getElementById('#app')
console.log(element.dataset)
console.log(element.dataset.taste) // あるはず
const dataset = JSON.parse(JSON.stringify(element.dataset)); // Object.assignがSafariではうまくいかないため
ReactDom.render(<App {...dataset} />, element);
ちなみにこのテクは、僕が作ったQiita Widgetで使っています。このへんのコードです→https://github.com/suin/qiita-widget/blob/master/src/main.js#L10
回答に対しての反応
おお、今か書いて下さったdatasetで切り替えるのが良さそうです! Safariでダメなのも知らなかったです。