React Material-UI Snackbarのカスタマイズに挑戦した

# 前提
React Material-UIのSnackbarコンポーネントアニメーションを自分好みにカスタマイズしてみまました。
React × Material-UIの記事が少ないので、内容コアですが、記事にしてみました。

# Snackbar（スナックバー）とは
スナックバーは、実行プロセスをユーザーに通知するための表現です。
<a href="https://gyazo.com/ce14b779e16b67f93476692d47ef63f4"><img src="https://i.gyazo.com/ce14b779e16b67f93476692d47ef63f4.gif" alt="Image from Gyazo" width="1000"/></a>


こちらのスライドアニメーションのカスタマイズに挑戦します。

# Snackbarコンポーネントの構造
Material-UIの構造の多くは、atom要素を構成しています。
今回の`Snackbar`も同様に、複数のatom要素でできています。


ReactのChrome拡張ツールなどでコンポーネント構造を見ると以下のようになっています。

```
<Snacbar>
  <ClickAwayListener>
    <Transition>
      <Slide>　// デフォルトは<Grow>
        <SnackbarContent>
```

もちろん、利用時に、テキスト構造など`Snackbar`のコンポーネント内に渡してあげると構造は変化します。

## APIについて
`Snackbar`コンポーネントに用意されたコンポーネントは主に以下があります。（[公式サイト](https://material-ui.com/ja/api/snackbar/)）

- action
    - スナックバーの最後にレンダリングされる要素
- anchorOrigin
    - アンカー要素
- autoHideDuration
    - スナックバーの表示時間
- message
    - スナックバーに表示されるメッセージ
- onClose
    - 閉じるリクエストが起こった場合のコールバック
- open
    - 表示
- TransitionComponent
    - トランジションに使用されるコンポーネント
- TransitonProps
    - トランジション要素のプロパティ
- transitonDuration
    - トランジション期間の設定


# Snackbarの実装
特別な要素指定を行わずに`Snackbar`の組み込みをしてみました。

```react

import React from 'react';
import Button from '@material-ui/core/Button';
import Snackbar from '@material-ui/core/Snackbar';
import Slide from '@material-ui/core/Slide';
import ClearIcon from '@material-ui/icons/Clear';

// FIXME：せっかくTransitionPropsプロパティあるのでそちらでdirection設定したい...
function Transition(props) {
  return <Slide {...props} direction="left" />;
}

export default function App() {
  const [open, setOpen] = React.useState(false);

  const handleOpen = () => {
    setOpen(true);
  };
  const handleClose = () => {
    setOpen(false)
  };

  return (
    <div className="App">
      <Button variant="contained" onClick={handleOpen}>Register</Button>
      <Snackbar
        open={open}
        message="Complete！"
        onClose={handleClose}
        TransitionComponent={Transition}
        action={<ClearIcon onClick={handleClose}/>}
      />
    </div>
  );
}
```

### `TransitionProps`がよくわからない
`Slide`コンポーネントの組み込み方が気持ち悪いですが、なせか、`TransitionProps`がうまく効きませんでした...
（原因わかったり、対応方法見つけたらまたそのタイミングで...わかる方いましたらコメントいただけると嬉しいです。。）

## コードについて
`Button`コンポーネントの押されたタイミングでスナックバーが表示されます。
`Snackbar`の`action`に閉じるアイコンを設置して`onClick`イベントでスナックバーを閉じれるように設定しています。

`Snackbar`の`onClose`オプションを指定して、いると、スナックバー外の要素アクションでも閉じるようです。


# アニメーションカスタマイズ
スナックバーで`TransitionComponent`を指定しなければ`Grow`コンポーネントが標準で用意されているようです。
上のコードでは`Slide`コンポーネントを使って横から入ってくるようにしています。

標準のTransitionが動くと、結構モーションが速いので、少しゆっくりめにカスタマイズしてみます。

## `transitonDuration`プロパティ
こちらのプロパティで`enter`と`exit`指定で入ってくるモーションと、出ていくモーションの指定が行えます。

```

transitionDuration={{
  enter: 800,
  exit: 800,
}}
```

モーション指定を行った後のソースは以下です。

```react

import React from 'react';
import Button from '@material-ui/core/Button';
import Snackbar from '@material-ui/core/Snackbar';
import Slide from '@material-ui/core/Slide';
import ClearIcon from '@material-ui/icons/Clear';

// FIXME：せっかくTransitionPropsプロパティあるのでそちらでdirection設定したい...
function Transition(props) {
  return <Slide {...props} direction="left" />;
}

export default function App() {
  const [open, setOpen] = React.useState(false);

  const handleOpen = () => {
    setOpen(true);
  };
  const handleClose = () => {
    setOpen(false)
  };

  return (
    <div className="App">
      <Button variant="contained" onClick={handleOpen}>Register</Button>
      <Snackbar
        open={open}
        message="Complete！"
        onClose={handleClose}
        TransitionComponent={Transition}
        transitionDuration={{
          enter: 800,
          exit: 800,
        }}
        action={<ClearIcon onClick={handleClose}/>}
      />
    </div>
  );
}
```

<a href="https://gyazo.com/b56115500c210e82b9e88c11e301bf75"><img src="https://i.gyazo.com/b56115500c210e82b9e88c11e301bf75.gif" alt="Image from Gyazo" width="918"/></a>


アニメーションの変更ができました！

# さいごに
Material-UIを使うと手軽に様々なモーション、インタラクションの活用ができてすごく便利ですが、そこに縛られてしまうこともあります。
この辺りの細かいオプションが用意されていればすごく利便性上がりますが、ここに苦しめられることも多くあります。

同じようなコンポーネントでも用途が違うコンポーネントとして用意されているものも多くあります。
皆さんはReact開発ではどんなコンポーネント開発行ってますか？是非聞かせて欲しい。。

### 2020/3/15 CodeSandbox リンク追加しました！
[![Edit material-ui-snackbar](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/mineyuji/dev-material-ui/tree/master/?autoresize=1&fontsize=14&hidenavigation=1&theme=dark&view=preview)