ことの発端
Next.js + PixiJSでサイトをつくっていて、
useEffect(() => { if (!app) { return; } app.loader.add('resource-1', '/resource/1.png') .load((loader, resources) => { setResources(resources); }); } }, [app]); // appは一度しか登録されないし更新されない
みたいな感じのコードを書いた時、更新箇所によってはホットリロード時に、PIXI.loaders.Loaderがリソースを登録しなおそうとしてしまい、
'Error: Resource named "RESOURCE_NAME" already exists.'
と、エラーになるので非常に困ってました。
対策1(没案)
おそらくホットリロードが効く開発時しか困ることはないと思ったので、
useEffect(() => { if (!app) { return; } try { app.loader.add('resource-1', '/resource/1.png') .load((loader, resources) => { setResources(resources); }); } catch (err) { console.error(err); } }, [app]);
という感じでtry-catchで囲ってしまうことも検討したのですが、本当にエラーの時に握り潰してしまうのはよくなさそうなのでやめました。
(本当のエラーが拾えるかは謎ですが)
対策2(採用案)
console.dir(app.loader);
で、loaderの中身をみたところ、resetというメソッドを見つけたので、
useEffect(() => { if (!app) { return; } app.loader.reset() .add('resource-1', '/resource/1.png') .load((loader, resources) => { setResources(resources); }); } }, [app]);
という感じで毎回リセットしてから使うことにしました。
ドキュメントで確認したところ、resetというメソッドは見つからず、
継承元のREADMEにも記載は見つからなかったのですが、
継承元のソースコードに記載を見つけました。
/** * Resets the queue of the loader to prepare for a new load. */ reset(): this { this.progress = 0; this.loading = false; this._queue.reset(); this._queue.pause();
と書いてあるので、メソッドチェーンも効きますし、queueを空にしてくれるメソッドのようです。