LoginSignup
19
7

More than 1 year has passed since last update.

MUI (Material-UI) v5でmakeStylesが非推奨になったのでstyledを使ってみる

Last updated at Posted at 2021-11-20

Material UI v5が2021年9月16日にリリースされ、makeStylesが非推奨になってしまいライブラリをアップデートするためにmakeStylesからstyledに置き換え対応を行いました。

これからv4からv5への移行をこれから行う人のためになればと思いサンプルコードを使って記事にしました。

  • Material-UI v4 の記法サンプル
  • 実際に行った作業
    • MUI v5のライブラリを追加
    • import先の変更
    • styledを使ったコンポーネントへのスタイリングの適用
  • 完成品
  • 置き換えをした感想
  • 最後に

Material-UI v4 の記法サンプル

makeStylesを使用して自作hooksを作成して、各コンポーネントにclassNameをあてているDialogになります。

import { makeStyles, createStyles } from '@material-ui/core/styles';
import DialogTitle from '@material-ui/core/DialogTitle';
import DialogContent from '@material-ui/core/DialogContent';
import Dialog from '@material-ui/core/Dialog';

const useStyles = makeStyles((theme) => createStyles({
  title: {
    color: theme.palette.primary.main,
    borderBottom: `1px solid ${theme.palette.grey[300]}`
  },
  content: {
    color: theme.palette.grey[700]
  }
}));

export const SampleDialog: React.FC = (props) => {
  const classes = useStyles();
  const { handleClose, open, title, content } = props;
  return (
    <Dialog onClose={handleClose} open={open}>
      <DialogTitle className={classes.title}>
        {title}
      </DialogTitle>
      <DialogContent className={classes.content}>
        {content}
      </DialogContent>
    </Dialog>
  );
};

実際に行った作業

MUI v5のライブラリを追加
yarn add @mui/material @emotion/react @emotion/styled

ライブラリが@mui/~になっているのでアップデートではMUI v5にならないので気を付けてください。
別ライブラリになるのでv4とv5の共存ができるため、のんびり移行作業ができるのは地味にありがたいですね

import先の変更
import { styled } from '@mui/material/styles';
import DialogTitle from '@mui/material/DialogTitle';
import DialogContent from '@mui/material/DialogContent';
import Dialog from '@mui/material/Dialog';

@material-ui/core~から@mui/material/~へimportの向き先を変更
また@mui/material/stylesから今回使用するstyledのimportします。
@mui/systemからもstyledをimportできますが、こちらをimportしてしまうとテーマを参照できなくなってしまうので注意です。
詳しくは公式サイト MUI styledに説明があるのでこちらをご覧ください。

styledを使ったコンポーネントへのスタイリングの適用

styledという名前ですので、styled-componentsのように記述します。

const SampleDialogTitle = styled(DialogTitle)(({ theme }) => ({
  color: theme.palette.primary.main,
  borderBottom: `1px solid ${theme.palette.grey[300]}`
}));

const SampleDialogContent = styled(DialogContent)(({ theme }) => ({
  color: theme.palette.grey[700]
}));

完成品

コンポーネントからclassNameがなくなってすっきりしました。

import { styled } from '@mui/material/styles';
import DialogTitle from '@mui/material/DialogTitle';
import DialogContent from '@mui/material/DialogContent';
import Dialog from '@mui/material/Dialog';

const SampleDialogTitle = styled(DialogTitle)(({ theme }) => ({
  color: theme.palette.primary.main,
  borderBottom: `1px solid ${theme.palette.grey[300]}`
}));

const SampleDialogContent = styled(DialogContent)(({ theme }) => ({
  color: theme.palette.grey[700]
}));

export const SampleDialog: React.FC = (props) => {
  const { handleClose, open, title, content } = props;
  return (
    <Dialog onClose={handleClose} open={open}>
      <SampleDialogTitle>
        {title}
      </SampleDialogTitle>
      <SampleDialogContent>
        {content}
      </SampleDialogContent>
    </Dialog>
  );
};

置き換えをした感想

いろんな画面で使う小さめのコンポーネントだと置き換えが簡単にできました。
そこそこ大きいコンポーネントだとdivタグにそれぞれclassNameでCSSを適用している箇所があり、そういったコンポーネントに対して置き換えが非常に大変でした。
今回、紹介していませんでしたがMUI v5にはstyledとは別に各コンポーネントにsxというpropsがありそちらも合わせて使えば上記の問題は何とかなるのかなといった感じです。

最後に

styledはMUIで提供されているコンポーネント以外にもdivやspanといったタグにもスタリングして使用することができます。
今までSassを使ってこの要素の子要素にまとめてCSSをあてるということをやることが多かったのですが、styledを使えばこのdivはCSSが適用されていることが一目でわかるのも便利です。

import * as React from 'react';
import { makeStyles, createStyles } from '@material-ui/core/styles';
import Paper from '@material-ui/core/Paper';

const useStyles = makeStyles((theme) => createStyles({
  root: {
    '& > div': {
      color: theme.palette.primary.main
    }
  }
}));
export const SampleDialog: React.FC = () => {
  const classes = useStyles();
  return (
    <Paper className={classes.root}>
      <div>a</div>
    </Paper>
  );
};

このようにuseStylesの中身を見ないとただのdivにしか見えず実装者以外にはわかりずらいdivタグも一目でただのdivタグではないことがわかります。

import * as React from 'react';
import { Paper } from '@mui/material';
import { styled } from '@mui/material/styles';

const DivPrimary = styled('div')(({ theme }) => ({
  color: theme.palette.primary.main
}));

export const SampleDialog: React.FC = () => {
  return (
    <Paper>
      <DivPrimary>a</DivPrimary>
    </Paper>
  );
};

19
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
7