前提
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開発ではどんなコンポーネント開発行ってますか?是非聞かせて欲しい。。