Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
208
Help us understand the problem. What is going on with this article?
@h-yoshikawa44

React入門 ~Material UI編~

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


※2020/09/24追記
この記事は Zenn に転載しました。
以降の更新は Zenn の方で行っていきますので、最新状態はそちらでご確認ください。


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);

Box コンポーネント(※2020/12/05追記)

HTML を書いていて、スタイルをあてるために要素を div や span で囲んで CSS を書くということがよくあります。
それと同じような感覚で扱える、Box コンポーネントというものが存在しており、なかなか便利です。

下記のコードの例ではmと指定していますが、これはmarginを意味します。
スペースのデフォルトテーマ値は8であるため、8 * 2 = 16px が実際の設定値となります。

import React from "react";
import { Box, Button } from '@material-ui/core';

const App = () => {
  return (
    <Box m={2}>
      <Button variant="contained">Test</Button>
    </Box>
  );
}

export default App;

この 8px というのは、マテリアルデザインにおいて使われる値で、この値を基準として要素を配置していくようになっています。
そのため、Box コンポーネントを使うと、簡単にその配置ができるというわけです。

あてられるスタイルとその props の書き方の種類は、公式ドキュメントのドロワーの System 配下のページを参照ください。

テーマの適用

(※2020/12/05修正)

@material-ui/coreには、全体のスタイル定義であるテーマ情報も含まれており、デフォルトで適用されています。

Material UI のコンポーネントは props でスタイルのカスタマイズができますが、その設定名称と実際の設定値との紐づけ情報は、このテーマで持っているわけです。

@material-ui/core/stylesuseThemeで、そのテーマ情報にアクセスし使用できます。

import React from "react";
import { Button } from "@material-ui/core";
import { useTheme } from "@material-ui/core/styles";

const App = () => {
  const theme = useTheme();
  return (
    <Button
      variant="contained"
      style={{ backgroundColor: theme.palette.primary.light }}
    >
      Test
    </Button>
  );
};

export default App;

テーマ情報に含まれている代表的なものとしては、以下のものがあります。

  • palette:パレットカラー
  • typography:フォントなど、文字に関する設定値(h1 などのタグ別のフォント情報も)
  • spacing:空白を計算する関数(デフォルトのベースは8pxで、8 * 引数 を返す)
  • breakpoints:ブレイクポイントの値と、メディアクエリ指定を補助する関数
  • z-index:z-index の設定値

このデフォルトテーマの内容に関しては、公式ドキュメント Customization - Default Themeでも確認できますが、 useThemeの返り値を console.log で見てみるのもありです。


自分で独自テーマを作りたい場合は、createMuiThemeを使った書き方ができます。
Material UI のデフォルトテーマを上書きするイメージです。

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

以下はテーマのパレットカラーを上書きしている例になります。

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

テーマ情報は各コンポーネント側で使用できます。
primary の元々の色は青ですが、変更しているので紫になります。
一方、secondary の色は変更していないので、デフォルトテーマの色が使われます。

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" color="secondary">secondary</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がどんなものなのか、大まかにでも伝わっていれば幸いです。

参考リンクまとめ

208
Help us understand the problem. What is going on with this article?
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
h-yoshikawa44
精神疾患持ちのWebプログラマー。 (リンクは個人ブログです) ※2020/09よりZennをメインにしていく関係上、Qiita記事の更新・投稿は基本的に停止していきます。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
208
Help us understand the problem. What is going on with this article?