React入門 ~Material UI編~

公開:2020/09/24
更新:2020/10/18
21 min読了の目安(約19500字TECH技術記事

React 入門記事、第4弾。
今回はUIコンポーネントを提供する Material UI のお話です。

この記事は、過去に Qiita および個人ブログへ投稿した記事に一部加筆・修正をしたものです。

Material UIとは?

公式:Material UI
Google の Material デザインをベースに開発された、UI コンポーネントライブラリです。

お手軽に Material デザインを取り入れられることに加えて、コンポーネントの種類が豊富に用意されているため、それらを組み合わせるだけでも見栄えの良いものを作ることができます。
一からコンポーネントを作るのはつらいとか、デザインを考えるのが難しいとか、それらに工数をあまりかけたくないなどの場合にもおすすめです。

React 向けの UI コンポーネントライブラリはいろんなものがありますが、その中で人気の高いライブラリでもあります。

執筆時点でのリポジトリスター数

こちらの記事で UI コンポーネントライブラリの紹介をされています。
早く・それなりの UI を実現する React コンポーネントセット 16 選

注意書き

あらかじめ言っておくのですが、今回はそこまで実践的なことは書いていません。
というのも、Material UI の機能を紹介するにしても、できることが多すぎてどこを抜粋するか悩んでしまったためです(苦笑)

公式ドキュメントを見ていただくとよくわかるのですが、あらゆる使用例、サンプルコード( JS、TS ともに)およびプレビュー表示が豊富に載っています。さらっと見ていくだけでも、こんなコンポーネントも用意されているのかと発見があって楽しいくらいです。

なので、提供されているコンポーネントに関しては、大まかな概要を紹介する程度にとどめます。
もし興味がわいた方はぜひ公式ドキュメントを見てみてください。
各コードには CodeSandbox へのリンクもあるので、お気軽に試せますよー。

インストール

一言で Material UI と言っても、ライブラリ的にはいくつかに分かれています。
その中で基本となるのが @material-ui/coreで、このライブラリだけでもほとんどのコンポーネントが使用できます。

$ yarn add @material-ui/core

今回の使用バージョンは4.9.10です。

その他のライブラリとしては以下のようなものがあります。必要に応じて適宜インストールしてください。

  • @material-ui/icons:SVG アイコンコンポーネント集(アイコン一覧:Material UI - Material Icons
  • @material-ui/lab:トグルボタンなど、core にはないコンポーネント集
  • @material-ui/pickers:Date Picker 的なコンポーネント集

使い方

以下、記載しているコードは公式ドキュメントのコードを元にしています。
画像や GIF に関しても、公式ドキュメントのプレビューが撮影元です。

基本的な使い方

使いたいコンポーネントを import して使用。
独自定義のコンポーネントを使用する時とほぼ同じですが、コンポーネントによった props の値を設定して見た目のカスタマイズができます。

import React from 'react';
import Button from '@material-ui/core/Button';

const App = () => {
  return (
    <Button variant="contained" color="primary">
      Test
    </Button>
  );
}

export default App;

スタイルのカスタマイズ

各コンポーネントの props でカスタマイズできる範囲外で、自分であてるスタイルをカスタマイズも可能です。

CSS プロパティ名はキャメルケースで記述することに注意です。

Hooks式

@material-ui/core/stylesmakeStylesを使います。

定義したスタイルをclassesにいれておいて、それを各要素に割り当てていく方式です。
従来の HTML・CSS のやり方に近いですね。

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';

const useStyles = makeStyles({
  button: {
    backgroundColor: 'green'
  }
});

const MaterialUIHooks = () => {
  const classes = useStyles();
  return (
    <Button variant="contained" className={classes.button}>
      Test
    </Button>
  );
}

export default MaterialUIHooks;

Styled Component式

@material-ui/core/stylesstyledを使います。

あらかじめスタイルをあてたコンポーネントを作成し、それを使用していくようなイメージです。

import React from 'react';
import { styled } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';

const CustomButton = styled(Button)({
  backgroundColor: 'red'
});

const MaterialUIStyled = () => {
  return (
    <CustomButton>Test</CustomButton>
  );
}

export default MaterialUIStyled;

HOC式(※旧式)

@material-ui/core/styleswithStylesを使います。

withStylesでラップすることにより、定義したスタイルとコンポーネントを結合。スタイルの情報は props の classes に格納されるので、それを各要素に割り当てていきます。
こちらも従来の HTML・CSS のやり方に近いですね。

import React from 'react';
import { withStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';

const styles = {
  button: {
    backgroundColor: 'orange'
  }
};

const MaterialUIHOC = props => {
  const { classes } = props;
  return (
    <Button variant="contained" className={classes.button}>
      Test
    </Button>
  );
}

export default withStyles(styles)(MaterialUIHOC);

テーマの適用

全体で共通して使用するようなスタイルを、あらかじめテーマとして定義しておいて使うこともできます。

ルート階層にてThemeProviderコンポーネントでアプリのコンポーネントをラップすることで、下層のコンポーネントにテーマ情報を渡します。

import { ThemeProvider } from '@material-ui/core/styles';
.
.
.
const theme = {
  color: 'blue',
};
.
.
.
ReactDOM.render(
  <ThemeProvider theme={theme}>
    <App />
  </ThemeProvider>,
  document.getElementById('root')
);

あとは各コンポーネント側で使用できます。

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';

const useStyles = makeStyles((theme) => ({
  button: {
    backgroundColor: theme.color
  }
}));

const MaterialUIHooks = () => {
  const classes = useStyles();
  return (
    <Button variant="contained" className={classes.button}>
      Test
    </Button>
  );
}

export default MaterialUIHooks;

また、createMuiThemeを使った書き方もできます。
こちらの場合は Material UI のデフォルトのパレットカラーを変更も可能です。

デフォルトのパレットカラーについてはこちらを参照。

import { ThemeProvider } from '@material-ui/core/styles';
import purple from '@material-ui/core/colors/purple';
import green from '@material-ui/core/colors/green';
.
.
.
const theme = createMuiTheme({
  palette: {
    primary: purple,
    secondary: green,
  },
  status: {
    danger: 'orange',
  },
});
.
.
.
ReactDOM.render(
  <ThemeProvider theme={theme}>
    <App />
  </ThemeProvider>,
  document.getElementById('root')
);

こちらも同様に各コンポーネント側で使用できます。
primary の元々の色は青ですが、変更しているので紫になります。

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';

const useStyles = makeStyles((theme) => ({
  button: {
    backgroundColor: theme.status.danger
  }
}));

const MaterialUIHooks = () => {
  const classes = useStyles();
  return (
    <div>
      <Button variant="contained" color="primary">primary</Button>
      <Button variant="contained" className={classes.button}>
        danger
      </Button>
    </div>
  );
}

export default MaterialUIHooks;

その他スタイルの書き方

このクラスの中のこの要素や、この要素のこのアクションといったような、ネストのスタイル指定はこのようになります。

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography';

const useStyles = makeStyles({
  msg: {
    color: 'blue',
    '& span': {
      color: 'red',
      '&:hover': {
        color: 'black'
      }
    }
  }
})

const MaterialUIHooks = () => {
  const classes = useStyles();
  return (
    <Typography className={classes.msg}>
      これは<span>テスト</span>です
    </Typography>
  )
}

export default MaterialUIHooks;

コンポーネント側でスタイルの値を指定する場合はuseStylesの引数に渡して、その値をスタイル定義側で使うようにします。

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';

const useStyles = makeStyles({
  button: props => ({
    backgroundColor: props.backgroundColor
  })
})

const MaterialUIHooks = () => {
  const props = { backgroundColor: 'gray'};
  const classes = useStyles(props);
  return (
    <Button variant="contained" className={classes.button}>
      Test
    </Button>
  )
}

export default MaterialUIHooks;

コンポーネントの種類

大まかな種類の概要だけさらっと書きます。
なので、ここに書いているもの以外のコンポーネントもあります。
(それでも長くなりました...)

()はどのライブラリに属しているかです。

Layout

他のコンポーネントをラップして使われる、レイアウトに関するコンポーネント集。

Box(core)

他のコンポーネントをラップし、スタイルをあてるためのコンポーネント。デフォルトでは div としてラップするが、他のものに指定もできる。
あてられるスタイルの種類は、公式ドキュメントのドロワーの System 配下のページを参照。

Container(core)

中央揃えするコンポーネント。

Grid (core)

グリッドレイアウトを表現するためのコンポーネント。

GridList、GridListTile、GridListTileBar(core)

画像をグリッドリストとして表現するためのコンポーネント。

Hidden(core)

コンポーネントを非表示にするコンポーネント。ブレイクポイントを設定して、画面幅によって非表示にするなどができる。

Inputs

フォームなどで使用する、入力に関するコンポーネント集。

Button、IconButton(core)

ボタンコンポーネント。
Button はシンプルなものから、枠線あり、塗りつぶしのパターン。アイコンと組み合わせたものなど、いろんなパターンに対応。
IconButton はアイコン自体をボタンにしたもの。

Button の例
button.png

IconButton の例
icon-button.png

ButtonGroup(core)

ボタンをグループ化したコンポーネント。

ButtonGroup の例
button-group.png

Checkbox(core)

チェックボックスコンポーネント。FormControlLabel と組み合わせることで、ラベル付きのものも作れる。

Checkbox の例( FormControlLabel と組み合わせ)

check-box.png

Fab(core)

Floating Action Button の略。少し浮いているようなボタンのコンポーネント。

Fab の例
fab.png

MuiPickersUtilsProvider, KeyboardTimePicker, KeyboardDatePicker( pickers )

Date Picker 的なコンポーネント。
詳細は Material-UI Pickers から。

KeyboardDatePicker の例( variant="inline" )

date-picker-inline.gif

KeyboardDatePicker の例( variant="dialog" )

date-picker-dialog.gif

KeyboardTimePicker の例

time-picker.gif

RadioGroup、Radio(core)

ラジオボタンコンポーネント。FormControlLabel と組み合わせることで、ラベル付きのものも作れる。

RadioGroup、Radioの例
radio.png

Select(core)

セレクトボックスコンポーネント。選択肢をグルーピングもできる。

Selectの例
select.gif

Slider(core)

スライダーコンポーネント。

Slider の例
slider.png

Switch(core)

スイッチコンポーネント。FormControlLabel と組み合わせることで、ラベル付きのものも作れる。

Switch の例
switch.png

Text Field(core)

テキスト入力フォームのコンポーネント。マルチラインにしたり、セレクトボックスにしたりもできる。また、フォームにアイコンをつけたり、単位の文字をつけるといったことも可能。

TextField の例
textfield.png

ナビゲーションに関するコンポーネント集。

BottomNavigation、BottomNavigationAction(core)

スマホアプリでよくあるような、ボタンナビゲーションコンポーネント。

BottomNavigation、BottomNavigationAction の例

bottom-navigation.png

パンくずリスト的なコンポーネント。Linkと組み合わせたりする。

Breadcrumbs の例
breadcrumbs.png

Drawer(core)

ドロワーコンポーネント。Button と組み合わせて、クリックされたときにドロワーを開くといったように使う。
画面の上下左右どこからドロワーが開くか設定できる。

Drawer の例(上から開いた例)
drawer.gif

Link(core)

リンクコンポーネント。React Router を併用する場合は、あまり使う機会ないかも?

Link の例
link.png

メニューコンポーネント。Button と組み合わせて、クリックされたときにメニューを開くといったように使う。

Menu、MenuItem の例(メニューを開いた後)
menu.gif

Stepper、StepLabel(core)

ステッパーコンポーネント。ステップ手順を踏んでいくような表現ができる。

Stepper、StepLabel の例
stepper.png

Tabs(core)

タブコンポーネント。アイコンを使って、ボタンナビゲーションのようにもできる。

Tabs の例
tabs.png

Surfaces

表面的な UI に関するコンポーネント集。

AppBar、ToolBar(core)

ヘッダーに使えるようなバーのコンポーネント。

AppBar、ToolBar の例
app-bar.png

Paper(core)

積み重なった紙のような表現ができるコンポーネント。

Paper の例
paper.png

Card、CardActionArea、CardActions、CardContent、CardHeader、CardMedia(core)

カードコンポーネント。文字だけでなく画像もいれられる。

Card、CardActions、CardContent、CardHeader、CardMedia の例

card.png

ExpansionPanel、ExpansionPanelActions、ExpansionPanelDetails、ExpansionPanelSummaly(core)

ハンバーガメニューのようなコンポーネント。

ExpansionPanel、ExpansionPanelDetails、ExpansionPanelSummaly の例

expansion-panel.gif

Feedback

ユーザに状態を伝えるようなコンポーネント集。

CircularProgress、LinearProgress(core)

プログレスコンポーネント。読み込み中の表現ができる。

CircularProgress の例
progress.gif

Dialog、DialogActions、DialogContent、DialogContentText、DialogTitle(core)

ダイアログコンポーネント。Button と組み合わせて、クリックされたときにダイアログを開くといったように使う。

SimpleDialog の例
dialog.gif

Snackbar(core)

スナックバーコンポーネント。Button と組み合わせて、クリックされたときにメッセージを出すといったように使う。

Snackbar の例
snack-bar.gif

Backdrop(core)

アプリ上の状態変化を表現できる、背景のコンポーネント。

Backdrop の例( CircularProgress との組み合わせ)

backdrop.gif

Data Display

データを表示することに関するコンポーネント集。

Avatar、AvatarGroup(core)

アバターコンポーネント。画像や名称を指定してユーザのアイコンのような表現ができる。

Avatar の例
avatar.png

Badge(core)

バッジコンポーネント。アイコンなどと組み合わせて通知を表現できる。

Badge の例
badge.png

Chip(core)

チップコンポーネント。入力や属性、アクションを表現できる。

Chip の例
chip.png

Divider(core)

線を表現できるコンポーネント。デフォルトではhrとして変換される。

Divider の例(線の部分)
divider.png

Material Icons( icons )

アイコンのコンポーネント集。アイコンの種類は Material UI - Material Icons を参照。

List、ListItem、ListItemAvatar、ListItemIcon、ListItemSecondaryAction、ListItemText、ListSubHeader(core)

リスト表示を表現できるコンポーネント。

List、ListItem、ListItemIcon、ListItemText の例

list.png

Table、TableBody、TableCell、TableContainer、TableFooter、TableHead、TablePagination、TableRow、TableSortLabel(core)

テーブル表示を表現できるコンポーネント。テーブル内のパーツごとにコンポーネントが分かれており、ソート機能も導入できる。

Table、TableBody、TableCell、TableContainer、TableHead、TableRow の例

table.png

Tooltip(core)

ツールチップコンポーネント。ラップしているコンポーネントをホバーした時に、簡易説明を表示するような表現ができる。

Tooltip の例
tooltip.gif

Typography(core)

文字表示を表現できるコンポーネント。文字位置や文字色、どのタグ(h1など)とするか、どのタグのスタイルをあてるかなどを設定できる。

Typography の例
typography.png

Utils

ユーティリティ的なコンポーネント集。

ClickAwayListener(core)

要素の外でクリックイベントが発生したかどうかを検出するコンポーネント。

CSSBaseline、ScopedCssBaseline(core)

normalize.css のような、CSS をリセットするコンポーネント。ブラウザごとの表示を統一したい時に使用。

Modal(core)

モーダルコンポーネント。Dialog、Drawer、Menu、Popover から活用されている下位レベルの要素。

Modal の例
modal.gif

NoSsr(core)

ラップしたコンポーネントを SSR(サーバサイドレンダリング)の対象から外すコンポーネント。
SSR の時間を短縮、SSR に対応していないコンポーネントをエスケープなどに使う。

Popover(core)

ポップオーバーコンポーネント。コンテンツを別のコンテンツの上に表示する表現ができる。

Popover の例
popover.gif

Popper(core)

ポッパーコンポーネント。これもコンテンツを別のコンテンツの上に表示する表現ができる。
上に表示されたコンテンツはスクロールについてこないなど、Popover と微妙な違いがある。

Popperの例
popper.gif

Portal(core)

ポータルコンポーネント。ラップしたコンポーネントを現在の DOM 階層外の新しいサブツリーへレンダリングすることに使う。

TextareaAutosize

テキストエリアコンポーネント。デフォルトでは自由にサイズを変更できるが、サイズや行数を固定することも可能。

TextareaAutosize の例
textarea.gif

Collapse(core)

ラップしたコンポーネントで、上から下へ表示される表現ができるコンポーネント。

Collapse の例
collapse.gif

Fade(core)

ラップしたコンポーネントで、フェードイン、フェードアウトを表現できるコンポーネント。

Fade の例
fade.gif

Grow(core)

ラップしたコンポーネントを順番にフェードインするような表現ができるコンポーネント。

Grow の例
grow.gif

Slide(core)

ラップしたコンポーネントをスライド表示する表現ができるコンポーネント。スライドする方向は指定できる。

Slide の例(derection="up")
slide.gif

Zoom(core)

ラップしたコンポーネントが、要素の中心から外側に広がるように表示する(もしくはその逆)表現ができるコンポーネント。

Zoom の例
zoom.gif

Lab

まだ core へは組み込まれていないコンポーネント集。

Alert、AlertTitle(lab)

アラートコンポーネント。ユーザへ促す注意や案内を表現する。

Alert の例
alert.png

Autocomplete(lab)

サジェスト入力フォームを実現できるコンポーネント。複数選択式にすることも可能。

AutoComplete の例
auto-complete.gif

Pagination、PaginationItem(lab)

ページネーションを表現できるコンポーネント。

Pagination の例
pagination.png

Rating(lab)

レーティングを表現できるコンポーネント。

Rating の例
rating.gif

Skeleton(lab)

コンテンツの読み込み中にスケルトンを表示するような表現ができるコンポーネント。

Skeleton の例
skeleton.gif

SpeedDial、SpeedDialIcon、SpeedDialAction(lab)

スピードダイヤルで3~6の関連アクションを表示するような表現ができるコンポーネント。

SpeedDial、SpeedDialIcon、SpeedDialAction の例

speed-dial.gif

ToggleButton、ToggleButtonGroup(lab)

トグルボタンコンポーネント。

ToggleButton、ToggleButtonGroup の例

toggle-button.png

TreeView、TreeItem(lab)

ツリービューを表現できるコンポーネント。

TreeView、TreeItem の例
tree-view.png


概要だけさらっと書くつもりがすごく長くなってしまいました。
ここまで読んでくださった方、ありがとうございます!

それだけ提供している機能が多いということでもあるので、味方につけるときっと頼もしい存在になってくれるのではないかと。
ちなみに自分が業務で使用していた時に、使用バージョンだと対応してなくて泣く泣く使うことができなかった機能もありました(笑)

この記事を書くにあたって、改めて公式ドキュメントを読んで新しい発見もあって、より使いこなせるようになりたいなと思いました。
Material UI がどんなものなのか、大まかにでも伝わっていれば幸いです。

参考リンクまとめ

シリーズ記事リンク