2020-12-29
props で指定された URL が変わったら フェードアウト し、
新しい URL 画像で フェードイン しながら表示するコンポーネントを作りました。
react-transition-group
を使います。
デモ
コード
import React, { useState } from 'react'
import { Transition } from 'react-transition-group'
const duration = 1000
const defaultStyle = {
transition: `opacity ${duration}ms ease-in-out`,
opacity: 0,
}
const transitionStyles = {
entering: { opacity: 1 },
entered: { opacity: 1 },
exiting: { opacity: 0 },
exited: { opacity: 0 },
}
type Props = { url: string }
function FadeChanger({ url }: Props) {
const [currentUrl, setCurrentUrl] = useState<string>(url)
return (
<Transition
in={url === currentUrl}
onExited={() => setCurrentUrl(url)}
timeout={duration}
>
{(state) => (
<div
style={{
width: '100px',
height: '100px',
background: `url(${currentUrl})`,
...defaultStyle,
...transitionStyles[state],
}}
></div>
)}
</Transition>
)
}
<Transition in={url === currentUrl}
部分の説明。
変更された際 in={false}
になり Exit アニメーション(fade out)をする。
Exit アニメーション終了後 onExited={() => setCurrentUrl(url)
により in={true}
になり Enter アニメーション(fade in)をする。
(hooks 使って書きたい…。)
呼び出す側のコード
const Demo = () => {
const [num, setNum] = useState<number>(0)
const incNum = () => setNum((v) => v + 1)
return (
<div>
<FadeChanger
url={`https://avatars.dicebear.com/4.5/api/male/${num}.svg`}
/>
<button onClick={incNum}>change</button>
</div>
)
}
props を変えるだけなので直感的に使えます。
DiceBear Avatars について(余談)
DiceBear Avatars
https://avatars.dicebear.com/SVG を生成するモジュールもありますが、ダイレクトリンクの HTTP API が推奨されています。
人間以外にもロボットやシンボルや Identicon
(GitHub のデフォルトアイコン) のようにいろんな種類が作られています。
Overview | DiceBear Avatars
https://avatars.dicebear.com/styleshttps://avatars.dicebear.com/4.5/api/male/[文字列].svg
で使用できます。