toshi-toma blog

主にフロントエンド、作業ログあとは色々なメモ ✍️ 🍅

Material-UIを使った開発

Material-UI

数ヶ月ほど、Material-UIを使った開発をしたので、知見などのメモです。

Material-UIは、MaterialデザインベースのReactのUIコンポーネントライブラリです。

material-ui.com

とても有名で、便利なコンポーネントがたくさん用意されています。

パッケージ

基本的には、@material-ui/coreをインストールすれば良いです。

追加で、アイコンを利用する場合は@material-ui/iconsをインストールします。

また、coreに入ってないコンポーネントが、@material-ui/labというパッケージで提供されているので、もし利用したくなったらインストールします。 自分の場合は、AlertやAutocompleteが使いたかったのでインストールしました。

情報

あまりネットに情報が無い印象なので、基本的に公式ドキュメントを見るだけです。 あとは、似たようなUIのTemplatesを見るくらいです。

material-ui.com

コンポーネント

Components

コンポーネントについては、ドキュメントの「Components」項目を見ると、見た目やパターン、サンプルコードを確認できます。

React Button component - Material-UI

ただし、コンポーネントごとにページが用意されているわけではなく、「Button」や「Card」といったある程度のまとまりでページが用意されています。

例えば、「Card」コンポーネントの場合、ページの下部に「API」という項目があり、「Card」以外にも「CardActionArea」や「CardActions」といった関連するコンポーネントAPIページへの導線が記されています。

React Card component - Material-UI

Component API

「Component API」という項目もあり、こちらは全コンポーネントのPropsなどの情報が書いてあります。逆に見た目やパターンなどは書いてないので、「Components」ページを見る必要があります。

Button API - Material-UI

よく使うコンポーネント

  • Button
    • 基本的にボタンはこれ
  • IconButton
    • アイコンだけのボタンの場合はこれ
  • Card
    • カード
  • Grid
    • レイアウトはだいたいGridでいい感じにできる
  • Paper
    • ある程度の区切りをPaperで作る
  • Dialog
    • ダイアログ
  • Snackbar、Alert
    • エラーや成功時のフィードバックに使う
  • Table
    • テーブル
  • Typography
    • 文字は基本的にこれ
  • Checkbox、Radio、Select、TextField、FormControl
    • フォーム
  • App Bar
    • よくあるヘッダー
  • Progress
    • ローディング

アイコン

以下のページで、それっぽいキーワードで検索する

Material Icons - Material-UI

その他

普段の開発では、まず「Components」ページで、見た目やサンプルコードを確認して、Props情報などが知りたくなったら「Component API」ページを見ていました。

また、全体的にどんなコンポーネントがあるのかみたい場合は、以下のFigmaを見るといいかもしれません。

Material-UI for Figma | Material-UI Store

DateTimePicker(日時)

DateTimePickerが欲しくなった際は、以下の「Material-UI Pickers」が用意されています。

material-ui-pickers.dev

このライブラリは、ユーザーがdate-fnsdayjsといった日時操作系のライブラリと組み合わせて使えるようになっています。自分の場合は、dayjsと組み合わせて使いました。

以下のように、dayjs以外に、@date-io/dayjsパッケージをインストールします。

$ npm i -s @date-io/dayjs@1.x dayjs

あとは、Providerを設定します。

import { MuiPickersUtilsProvider } from "@material-ui/pickers";
import DayjsUtils from "@date-io/dayjs";

import Root from "./Root";

function App() {
  return (
    <MuiPickersUtilsProvider utils={DayjsUtils}>
      <Root />
    </MuiPickersUtilsProvider>
  );
}

あとは、<DatePicker><DateTimePicker>といった用意されているコンポーネントを利用するだけです。

dayjs用の設定をしておいたので、valueにDayjsオブジェクトが使えたり、onChangeのdataがDayjsオブジェクトとして返ってきます。

type Props = {
  value: Dayjs;
  handleChange: (date: Dayjs) => void;
};
export const MyDateTimePicker: React.FC<Props> = ({ value, handleChange }) => (
  <KeyboardDateTimePicker
    variant="inline"
    ampm={false}
    value={value}
    onChange={(date) => {
      if (date) {
        handleChange(date);
      }
    }}
    format="YYYY/MM/DD HH:mm"
  />
);

スタイル

Material-UIには、core/stylesからmakeStylesというAPIが提供されており、CSS-in-JSスタイルでスタイリングをしていきます。

@material-ui/styles - Material-UI

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

const useStyles = makeStyles({
  root: {
    color: 'white',
    height: 48,
    padding: '0 30px',
  },
});

export default function MyButton() {
  const classes = useStyles();
  return <Button className={classes.root}>Hook</Button>;
}

また、CssBaselineというnormalize.cssに似た役割を持ったコンポーネントが用意されているので、アプリケーションのトップレベルで読み込むようにしました。

SSR(Next.js)

Next.jsで開発している際、「Prop className did not match」というエラーが出ます。 SSRとクライアントサイドでclassNameが変わってしまうので、_app.tsxに以下の記事で紹介されているような対応をしました。

github.com qiita.com

Theme

Material-UIで用意されているコンポーネントは色がprimarydefaultsecondaryといった形で指定します。

ここで適用される色はデフォルトのThemeです。

Default Theme - Material-UI

アプリケーションのデザインに合うように、Themeをカスタマイズしました。ThemeProviderを設定します。

material-ui.com

Themeの例

import { createMuiTheme } from "@material-ui/core/styles";
import blue from "@material-ui/core/colors/blue";
import red from "@material-ui/core/colors/red";

const theme = createMuiTheme({
  palette: {
    primary: {
      main: blue["600"],
    },
    secondary: {
      main: red["600"],
    },
  },
  typography: {
    h1: {
      fontWeight: 600,
    },
    h2: {
      fontWeight: 600,
    },
    button: {
      fontWeight: 600,
    },
  },
});

export default theme;

日本語だと、h要素でも細字になってしまったので、h要素のfontWeightを高く設定することも可能です。