Help us understand the problem. What is going on with this article?

React入門 ~Material UI編~

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

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;

※2020/05/06追記
また、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の例

IconButtonの例

ButtonGroup(core)

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

ButtonGroupの例

Checkbox(core)

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

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

Fab(core)

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

Fabの例

MuiPickersUtilsProvider, KeyboardTimePicker, KeyboardDatePicker(pickers)

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

KeyboardDatePickerの例(variant="inline")

KeyboardDatePickerの例(variant="dialog")

KeyboardTimePickerの例

RadioGroup、Radio(core)

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

RadioGroup、Radioの例

Select(core)

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

Selectの例

Slider(core)

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

Sliderの例

Switch(core)

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

Switchの例

Text Field(core)

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

TextFieldの例

Navigation

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

BottomNavigation、BottomNavigationAction(core)

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

BottomNavigation、BottomNavigationActionの例

Breadcrumbs(core)

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

Breadcrumbsの例

Drawer(core)

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

Drawerの例(上から開いた例)

Link(core)

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

Linkの例

Menu、MenuItem(core)

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

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

Stepper、StepLabel(core)

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

Stepper、StepLabelの例

Tabs(core)

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

Tabsの例

Surfaces

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

AppBar、ToolBar(core)

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

AppBar、ToolBarの例

Paper(core)

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

Paperの例

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

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

Card、CardActions、CardContent、CardHeader、CardMedia、の例

ExpansionPanel、ExpansionPanelActions、ExpansionPanelDetails、ExpansionPanelSummaly(core)

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

ExpansionPanel、ExpansionPanelDetails、ExpansionPanelSummalyの例

Feedback

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

CircularProgress、LinearProgress(core)

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

CircularProgressの例

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

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

SimpleDialog の例

Snackbar(core)

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

Snackbarの例

Backdrop(Core)

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

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

Data Display

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

Avatar、AvatarGroup(core)

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

Avatarの例

Badge(core)

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

Badgeの例

Chip(core)

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

Chipの例

Divider(core)

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

Dividerの例(線の部分)

Material Icons(icons)

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

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

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

List、ListItem、ListItemIcon、ListItemTextの例

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

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

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

Tooltip(core)

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

Tooltipの例

Typography(core)

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

Typographyの例

Utils

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

ClickAwayListener(core)

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

CSSBaseline、ScopedCssBaseline(core)

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

Modal(core)

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

Modalの例

NoSsr(core)

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

Popover(core)

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

Popoverの例

Popper(core)

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

Popperの例

Portal(core)

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

TextareaAutosize

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

TextareaAutosizeの例

Collapse(core)

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

Collapseの例

Fade(core)

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

Fadeの例

Grow(core)

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

Growの例

Slide(core)

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

Slideの例(derection="up")

Zoom(core)

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

Zoomの例

Lab

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

Alert、AlertTitle(lab)

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

Alertの例

Autocomplete(lab)

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

AutoCompleteの例

Pagination、PaginationItem(lab)

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

Paginationの例

Rating(lab)

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

Ratingの例

Skeleton(lab)

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

Skeletonの例

SpeedDial、SpeedDialIcon、SpeedDialAction(lab)

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

SpeedDial、SpeedDialIcon、SpeedDialActionの例

ToggleButton、ToggleButtonGroup(lab)

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

ToggleButton、ToggleButtonGroupの例

TreeView、TreeItem(lab)

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

TreeView、TreeItemの例


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

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

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

参考リンクまとめ

h-yoshikawa
精神疾患持ちのWebプログラマー。 とりあえず興味のあること、色々やってます。 (リンクは個人ブログです)
https://changeofpace.site
froide
Webサービスやモバイルアプリの受託開発。アジャイルをベースとした月額制のラボ型契約。
https://froide.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした