前提
React Material-UIのSnackbarコンポーネントアニメーションを自分好みにカスタマイズしてみまました。
React × Material-UIの記事が少ないので、内容コアですが、記事にしてみました。
Snackbar(スナックバー)とは
スナックバーは、実行プロセスをユーザーに通知するための表現です。

こちらのスライドアニメーションのカスタマイズに挑戦します。
Snackbarコンポーネントの構造
Material-UIの構造の多くは、atom要素を構成しています。
今回のSnackbarも同様に、複数のatom要素でできています。
ReactのChrome拡張ツールなどでコンポーネント構造を見ると以下のようになっています。
<Snacbar>
<ClickAwayListener>
<Transition>
<Slide> // デフォルトは<Grow>
<SnackbarContent>
もちろん、利用時に、テキスト構造などSnackbarのコンポーネント内に渡してあげると構造は変化します。
APIについて
Snackbarコンポーネントに用意されたコンポーネントは主に以下があります。(公式サイト)
- action
- スナックバーの最後にレンダリングされる要素
- anchorOrigin
- アンカー要素
- autoHideDuration
- スナックバーの表示時間
- message
- スナックバーに表示されるメッセージ
- onClose
- 閉じるリクエストが起こった場合のコールバック
- open
- 表示
- TransitionComponent
- トランジションに使用されるコンポーネント
- TransitonProps
- トランジション要素のプロパティ
- transitonDuration
- トランジション期間の設定
Snackbarの実装
特別な要素指定を行わずにSnackbarの組み込みをしてみました。
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,
}}
モーション指定を行った後のソースは以下です。
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>
);
}
アニメーションの変更ができました!
さいごに
Material-UIを使うと手軽に様々なモーション、インタラクションの活用ができてすごく便利ですが、そこに縛られてしまうこともあります。
この辺りの細かいオプションが用意されていればすごく利便性上がりますが、ここに苦しめられることも多くあります。
同じようなコンポーネントでも用途が違うコンポーネントとして用意されているものも多くあります。
皆さんはReact開発ではどんなコンポーネント開発行ってますか?是非聞かせて欲しい。。
