React MaterialUIでのスタイルの当て方3選 簡単に特徴とメリデメ

##はじめに
私は今年からインターンをしていた会社に入社し、フロントエンドエンジニアとしてReact Reduxを使い開発を行っているものです。
HTML CSSは3ヶ月ほどかけて自社のランディングページを作成した時に触りました。初めてqiita書きます！

## styled-components
#### 特徴
- 各コンポーネントごとに必要なcssを記載し適応させる
- cssをコンポーネント毎に書くため、useStyles同様1ページのコード量は増えてしまう
- 要素の命名を自由に変えられるためコンポーネント内での責任による命名ができる。
- useStylesほどmaterialUIと密ではない

#### メリット
- 1ファイルでコードとcssが完結する。
- 要素内に`style={}`でcssを適応させるよりすっきりしてわかりやすい
- 要素名が`<Grid>`とか`<Button>`とかじゃなくて、`<ListWrapper>`とか`<FormSubmitButton>`とかにできるのでかっこいい！！！　＋　見ただけで何をしているか理解することができる
- intelliJを使っていますが、useStylesと違って、styleを当てている変数に飛べる。(useStylesはclassesに飛んじゃう)
- devtoolを使ってスタイル変更の確認をしてコピペでスタイルが適応される

#### デメリット
- 1ファイルで完結することの裏返しで、cssとコードが1ファイルに書かれるためコードが長くなってしまう
- 予測変換が全く出ない。間違ったcssも赤く出てくれない。間違った値を入れても赤くしてくれない。
- 疑似クラスがcssの記載の方法とは違ってる。私が未熟者だからですが、わかりづらい書き方している。
- materialUIを使っているとたまにunexpectedなdivが入ってくるが、それに対応しずらい。

#### Example
```styledComponent.tsx
import { Button, Grid, Paper, Typography } from "@material-ui/core";
import React from "react";
import styled from "styled-components";
type Props = {};

const StyledComponentModal: React.FC<Props> = () => {
  return (
      <StyledComponentModal
        style={{
          display: styledComponentModalOpen ? "block" : "none"
        }}
      >
        <ModalContentWrapper>
          <Typography variant={"h4"}>StyledComponent</Typography>
          <StyledTypography variant={"body1"}>
            hogehoge
          </StyledTypography>
          <SubmitButton>SUBMIT</SubmitButton>
          <StyledComponentUl>
            <li>1 li</li>
            <li>2 li</li>
          </StyledComponentUl>
        </ModalContentWrapper>
      </StyledComponentModal>
   );
export default StyledComponentModal;
  const StyledComponentModal = styled(Paper)`
    width: 800px;
    height: 700px;
    position: absolute;
    top: 300px;
    background-color: white;
  `;
  const ModalContentWrapper = styled(Grid)`
    display: flex;
    flex-direction: column;
    padding: 20px;
  `;
  const StyledTypography = styled(Typography)`
    letter-spacing: 1.4px;
    line-height: 1.6;
  `;
  const StyledComponentUl = styled.ul`//疑似クラス
    li { //
      color: orange;
    }
    li:nth-child(2):hover { //StyledComponentUl > li のhover時
      color: green;
    }
  `;
  const SubmitButton = styled(Button)`
    display: flex;
    justify-content: center;
    width: 100px;
    height: auto;
    background-color: #0066ff;
    color: white;
    :hover {
      color: black;
    }
  `;
  const SubmitButtonWrapper = styled(Grid)`
    display: flex;
    justify-content: center;
  `;
```
実行結果
![スクリーンショット 2020-08-27 23.50.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512456/c2627bdb-0343-3e6b-0700-102c690f1f05.png)

## useStyles
#### 特徴
- 各コンポーネントごとに必要なcssを記載し適応させる
- cssをコンポーネント毎に書くため、styledcomponents同様1ページのコード量は増えてしまう
- コードの書き方はcssとは違い、CamelCaseでプロパティー名を書き、valueには`''`で囲わなければいけない
- materialUIのexampleで使われている

#### メリット
- 1ファイルでコードとcssが完結する。
- materialUIのexampleに使用されているためコピペで大体使える
- 予測変換機能がついている


#### デメリット
- 1ファイルで完結することの裏返しで、cssとコードが1ファイルに書かれるためコードが長くなってしまう
- JSSなので開発のdevtoolでstyleを確認してコピーして貼ることができない。(CamelCaseとsnake-caseの違い、valueが""で囲ってないと反応しない、ちょっとの差だけどだるい)
- intelliJで指定しているclassNameに直接飛べない(classesに飛ぶ)

```useStyles.tsx
import { Button, Grid, Paper, Typography } from "@material-ui/core";
import { makeStyles } from "@material-ui/core/styles";
import React from "react";

const useStyles = makeStyles({
  useStylesModal: {
    width: "800px",
    height: "700px",
    position: "absolute",
    top: "300px"
  },
  modalContentWrapper: {
    display: "flex",
    flexDirection: "column",
    padding: "20px"
  },
  useStyleBody: {
    letterSpacing: "1.4px",
    lineHeight: "1.6"
  },
  row: {
    display: "flex",
    flexDirection: "row",
    justifyContent: "space-between"
  },
  useStylesRowTextField: {
    width: "49%"
  },
  fullTextField: {
    width: "100%"
  }
  const SubmitButton = styled(Button)`
    width: 100px;
    height: auto;
    background-color: #0066ff;
    color: white;
    : hover {
      color: black;
    }
  `;
  const SubmitButtonWrapper = styled(Grid)`
    display: flex;
    justify-content: center;
  `;
});
const UseStylesModal: React.FC<Props> = () => {
  return (
      <Paper
        className={classes.useStylesModal}
        style={{
          display: useStylesModalOpen ? "block" : "none"
        }}
      >
        <Grid className={classes.modalContentWrapper}>
          <Typography variant={"h4"}>UseStylesTestForm</Typography>
          <Typography variant={"body1"} className={classes.useStyleBody}>
             hogehoge
          </Typography>
        </Grid>
        <Grid className={classes.useStylesButtonWrapper}>
          <Button className={classes.useStylesButton}>SUBMIT</Button>
        </Grid>
      </Paper>
  );
}
export default UseStylesModal;
```

![スクリーンショット 2020-08-28 1.30.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512456/bfee75f8-9f3e-6c8d-f9a8-2719edb31f85.png)
ちょっとulないの子要素にたいしてスタイル適応できませんでした。消しました。すみません。

#### stylesProvider
#### 特徴
- 上で挙げた2つの方法とは違い、cssfileを別に用意して呼び出して使用する
- app.tsxで```<stylesProvider>```で囲ってあげる必要がある
- cssのコードを使いまわせることができる
- ページ毎に一つのcssfileを作成すればページ内の同じスタイルがあるとすれば適用させてあげることができる

#### メリット
- 予測変換がある
- cssファイルを別で書くため1ファイルのコードの少なくスッキリする
- cssの使い回しができる
- 疑似クラス、mediaqueryの当て方がベーシックに書ける

#### デメリット
- stylesProviderのトピックの記事が少ない
- 1ファイルで完結しない(ページごとに)



```app.tsx
import { StylesProvider } from "@material-ui/styles";
import React from "react";

const App = () => {
  return (
    <StylesProvider injectFirst>
      <TopList />;
    </StylesProvider>
  );
};

export default App;

```
```stylesProvider.tsx
import { Button, Grid, Paper, Typography } from "@material-ui/core";
import { StylesProvider } from "@material-ui/core/styles";
import React, { useState } from "react";
import "./style.css";
type Props = {};
const StylesProviderModal: React.FC<Props> = () => {
  return (
        <Paper
          style={{
            display: styledProviderModalOpen ? "block" : "none"
          }}
          className={"stylesProvider"}
        >
          <Grid className={"modalContentWrapper"}>
            <Typography variant={"h4"}>StyledProviderModal</Typography>
            <Typography variant={"body1"} className={"styledProviderBody"}>
               hogehoge
            </Typography>
            <ul className={"stylesProviderUl"}>
              <li>1 li</li>
              <li>2 li</li>
              <li>3 li</li>
            </ul>
          </Grid>
        </Paper>
  );
};
```
```styles.css
.stylesProvider{
    width: 800px;
    height: 700px;
    position: absolute;
    top: 300px;
}
.modalContentWrapper{
    display: flex;
    flex-direction: column;
    padding: 20px;
}
.styledProviderBody{
    letter-spacing: 1.4px;
    line-height: 1.6;
}
.fullTextField{
    width: 100%;
}
.row{
    display: flex;
    flex-direction: row;
}
.useStylesRowTextField{
    width: 49%;
}

.stylesProviderUl > li:nth-child(2){
    color: red;
}
.stylesProviderUl > li:hover{
    color: green;
}

body{
    background: aliceblue;
}
```
![スクリーンショット 2020-08-28 3.49.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512456/de730b1a-b472-9a44-4a1b-5dc975e1e89c.png)

### 個人的な感想
stylesProviderは実践で使用したことがないが、他2つの長所を合わせたようなものであった気がするし、
cssの再利用を考えた時に他の2つと比べて、秀でているところかなと思う。
まるっきりcssな為、cssの記法についてはいくらでもネットに転がっているので困ることがない。
mediaquery,疑似クラスで困ることもない！
めちゃめちゃ推したい。
ただ懸念点としては、英文、日本語共に記事がびっくりするほどなかった。

今後、stylesProviderを導入してみて、どれを使用していくか話し合いますがstylesProviderにならないかなあ。

デメリットなど知っている方がいましたら、意見が欲しいです！よろしくお願いします。