初めまして。
独学でプログラミングを勉強しており、現在Reactで初めてのWebサービス(タイピングゲーム)を作成しています。
今回、Reactの再レンダリングの抑制で詰まってしまったため、お力をお借りできませんでしょうか。
やりたいこと
useMemoなどを使用して、音声ファイルの再レンダリング(再取得)を抑制したい。
現在作っているサービスは、簡単なタイピングゲームで、単語がひとつづつ表示され、その単語を入力すると次の単語に表示が変わるという形になっています。
今回、新たに単語ごとに読み上げ音声が流れるようにしたところ、音声ファイルをAWS S3からたびたび再取得してしまい、動作が重くなってしまいました。そこで、ページ表示時に音声を取得したら、もう再レンダリングしないよう抑制したいです。
現状のコード
以下に、音声関係の主だったコードを抜き出しました。
(恐らく重要なのは、最初の6行ほどとは思いますが、念のため音声再生に使うコードまで記載しています。)
追記:1~6は全て同じ場所、App.tsxのexport default function App(props) {}内に記載してあります。
React
1//1.音声用の配列を定義 2const soundList = []; 3 4//2.AWS S3のURLと単語(props.Words)のidを使用して、音声ファイルのURLを作成&ロード 5 for (let i = 0; i < props.Words.length; i++) { 6 if (!props.Words[i]) continue; 7 soundList.push(new Audio(S3_BASE_URL + '+(' + props.Words[i].id + ').mp3') 8 ) 9 10//3.画面に表示されている単語と対応した音声ファイルを入れる定数を定義 11 const [audio, setAudio] = useState(soundList[0]); 12 13//audioのstateを更新する関数を定義 14 const updateSoundState = (wordId) => { 15 audio.pause(); 16 setAudio(soundList[wordId]); 17 } 18 19//4.単語の切り替えと同時に、音声も対応したものに切り替え(単語と音声ファイルの中から、変数numberで該当要素に切り替えています)。 20 useEffect(() => { 21 // audio更新 22 if(number<wordIdList.length){ 23 updateSoundState(number); 24 } 25 }, [number]); 26 27//5.音声ファイルを再生 28 useEffect(() => { 29 // audio再生 30 if(firstModalIsOpen==false){ 31 setTimeout( function() { 32 audio.currentTime = 0; //再生開始位置を先頭に戻す 33 audio.play(); //サウンドを再生 34 }, 10 ); 35 } 36 }, [audio]); 37 38
試したこと
下記のようにuseMemoを使用してみましたが、変化なしでした。
第2引数を変更するなど、試行錯誤してみましたが、うまくいきませんでした。
React
1//useMemoにて、配列に音声ファイルをpushするfor文を囲むも変化なし。 2const weightFunction = useMemo(() => { 3 for (let i = 0; i < props.Words.length; i++) { 4 if (!props.Words[i]) continue; 5 soundList.push(new Audio(S3_BASE_URL + '+(' + props.Words[i].id + ').mp3') 6 ) 7 } 8 return soundList; 9}, [soundList]);
また音声ファイルが再取得されるタイミングは、一定しておらず、法則性が良く分からないので原因もよくわかりません。
useMemoなどの再レンダリングの制御機能については、今回初めて勉強したため、的外れな質問となっていたら、申し訳ございません。
なにかお分かりの方がいらっしゃいましたら、ご教示いただけますと幸いです。
何卒宜しくお願い致します。
回答1件
あなたの回答
tips
プレビュー