React で classNames ライブラリを使用してMaterial UIコンポーネントをスタイリングする
Material UI では、classes
プロップを使用してコンポーネントにスタイルを適用できます。このプロップは、コンポーネントに適用されるCSSクラス名のオブジェクトを提供します。
複数のクラスを追加するには、以下の2つの方法があります。
スペースで区切る
最も簡単な方法は、クラス名をスペースで区切って className
プロパティに渡すことです。
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
const useStyles = makeStyles({
root: {
backgroundColor: '#f00',
color: '#fff',
},
active: {
fontWeight: 'bold',
},
});
const MyComponent = () => {
const classes = useStyles();
return (
<div className={`${classes.root} ${classes.active}`}>
{/* コンテンツ */}
</div>
);
};
上記の例では、MyComponent
コンポーネントは root
と active
の両方のクラスを持つ div
要素をレンダリングします。
classNames ライブラリを使用する
より柔軟な方法として、classNames
ライブラリを使用してクラス名を動的に生成することができます。
import React from 'react';
import classnames from 'classnames';
import { makeStyles } from '@material-ui/core/styles';
const useStyles = makeStyles({
root: {
backgroundColor: '#f00',
color: '#fff',
},
active: {
fontWeight: 'bold',
},
});
const MyComponent = ({ isActive }) => {
const classes = useStyles();
return (
<div className={classnames(classes.root, { [classes.active]: isActive })}>
{/* コンテンツ */}
</div>
);
};
上記の例では、MyComponent
コンポーネントは isActive
props に基づいて active
クラスを動的に追加します。
補足:
useStyles
hook を使用して、コンポーネント内でCSSクラス名を生成することをお勧めします。className
プロパティに直接文字列を渡すこともできますが、classes
プロップを使用すると、コードがより読みやすくメンテナンスしやすくなります。- Material UI v5 では、
useStyles
hook の代わりにstyled
コンポーネントを使用することができます。
Material UI で CSSクラス名を動的に生成する例
import React, { useState } from 'react';
import classnames from 'classnames';
import { makeStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
const useStyles = makeStyles({
button: {
padding: 10,
margin: 10,
},
primary: {
backgroundColor: '#007bff',
color: '#fff',
},
disabled: {
opacity: 0.5,
cursor: 'default',
},
});
const MyButton = () => {
const [isClicked, setIsClicked] = useState(false);
const classes = useStyles();
return (
<Button
className={classnames(classes.button, {
[classes.primary]: !isClicked,
[classes.disabled]: isClicked,
})}
onClick={() => setIsClicked(!isClicked)}
>
{isClicked ? '無効' : 'クリック'}
</Button>
);
};
export default MyButton;
この例では、以下のことが行われています。
useStyles
hook を使用して、button
、primary
、disabled
の3つのCSSクラスを生成します。MyButton
コンポーネントは、isClicked
state に基づいてprimary
とdisabled
クラスを動的に追加します。- ボタンがクリックされると、
isClicked
state が反転し、ボタンの色と状態が変更されます。
このコードをどのように拡張できますか?
- 異なるスタイルを持つ複数のボタンを作成します。
- ボタンの状態に応じて、テキストやアイコンを変更します。
- アニメーションを使用して、ボタンのインタラクションを強化します。
Material UI で複数のクラスを追加するその他の方法
前述の2つの方法に加えて、Material UI で複数のクラスを追加する方法は他にもいくつかあります。
spread operator
を使用して、classes
オブジェクトを className
プロパティに直接渡すことができます。
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
const useStyles = makeStyles({
root: {
backgroundColor: '#f00',
color: '#fff',
},
active: {
fontWeight: 'bold',
},
});
const MyComponent = () => {
const classes = useStyles();
return (
<div className={{ ...classes.root, ...classes.active }}>
{/* コンテンツ */}
</div>
);
};
この方法は、簡潔で読みやすいコードを作成できます。
css-in-js ライブラリを使用する
styled-components
や emotion
などの css-in-js
ライブラリを使用して、コンポーネント内でCSSを直接定義することができます。
import React from 'react';
import styled from 'styled-components';
const MyComponent = styled.div`
background-color: #f00;
color: #fff;
font-weight: bold;
`;
const MyButton = () => (
<MyComponent>
{/* コンテンツ */}
</MyComponent>
);
この方法は、より柔軟なスタイル設定が可能ですが、コードが冗長になる可能性があります。
コンポーネントの継承を使用する
スタイルを共有する必要があるコンポーネントがある場合は、コンポーネントの継承を使用することができます。
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
const useStyles = makeStyles({
common: {
backgroundColor: '#f00',
color: '#fff',
},
root: {
...classes.common,
padding: 10,
},
active: {
...classes.common,
fontWeight: 'bold',
},
});
const MyComponentBase = ({ classes }) => (
<div className={classes.root}>
{/* コンテンツ */}
</div>
);
const MyComponent = () => {
const classes = useStyles();
return (
<MyComponentBase classes={classes} />
);
};
この方法は、DRY(Don't Repeat Yourself)原則に従い、コードの重複を避けるのに役立ちます。
- シンプルなケースでは、スペースで区切るか
classNames
ライブラリを使用するのが最善です。 - より複雑なスタイル設定が必要な場合は、
spread operator
、css-in-js
ライブラリ、またはコンポーネントの継承を検討してください。
css reactjs material-design