あらまし
Nextで開発していたWEBアプリ上で、音を鳴らした後に処理をしたい事案があったが、日本語でドンピシャなサンプルが無かったので残しておく。使うのはuse-sound。
やりたいこと
特定の処理が走った際に、成功音や失敗音を鳴らしてから処理を走らせて再描画なり画面遷移なりをしたい。
使用技術
- React ^18
- use-sound: 4.0.3
シンプルな例
stateやcallback関数外に依存がない、複雑なことをしない、そんな場合はこちらのサイトにある通り、useSoundを使う際に onend
に関数を渡してあげればよい。
import se from "./se.mp3"
...(中略)...
const [play] = useSound(se, {
onend: () => {
console.log('再生完了')
}
})
一方で、一連の処理の中でstateを使ったりしながら、例えばPayPayなりWAONのようにキャッチーな音を鳴らした後にほげほげしたいみたいなことがあったときに、上の方法だと正しく動かない。
例えば以下のような場合は、onendの関数内でuserはnull
となる。
import se from "./se.mp3"
...(中略)...
const [user,setUser] = useState<User|null>(null)
const [play] = useSound(se, {
onend: () => {
console.log(user)
}
})
...略...
const handler = (user: User) => {
setState(user)
play();
}
解決
use-soundはHowler.jsをラップしているので、そちらから実装する。
まずは公式のドキュメントにあるように、型を入れておく。
yarn add -D @types/howler
or
npm i -D @types/howler
その上で、hookを呼び出す際にHowlオブジェクトを受け取り、イベントリスナを登録してあげる。このあたりの詳細はドキュメントを参照。
const [user,setUser] = useState<User|null>(null)
const [play, {sound}] = useSound(se)
...略...
const handler = (user: User) => {
sound?.once("end", async () => {
//再生終了後に呼ばれる
doSomePostProcess(user)
});
//音を鳴らす前の何らかの処理
doSomePreProcess(user)
//鳴らす
play();
}
以上で、やりたいことが実現できた🍻