React hookモジュールイジェクタ


🙈 Prologue


宣伝を始める前に、まず宣戦布告したいです.このエラーは、応答ホストのエンクロージャ依存性に起因するエラーです.このレポートでは、応答ホストを使用するときに必ず発生するエンクロージャ依存性から抜け出す方法に重点を置きます.なぜこのような依存性があるのか、REACTのHOOKを体現し、次の文章でさらに深く議論します!まず今回の宣伝で何があったのか、それがどうやって解けたのかを話したい.

更新された値は、⁉⁉を反映できません。


Youniverseの開発を行う際には,予想とは異なる動作コードに直面する.
 useEffect(() => {
  let timer = setInterval(() => {
    console.log(messageIndex);
    if (messages.length - 1 === messageIndex) {
      router.push('/onboarding');
    }else{
			setMessageIndex(messageIndex + 1);
		}
  }, 1500);
  return () => clearTimeout(timer);
}, []);
MessageIndexが+1になり、messagesと同じ長さになった場合、ルーティングが必要になるが、コンソール上の1500 msおきのmessageIndexは変わらず、常に0であることが分かった.
まず,この問題をすぐに解決するために,USEffectにMessageIndex値を1つ加えた.
useEffect(() => {
    let timer = setInterval(() => {
      if (messages.length - 1 === messageIndex) {
        router.push('/onboarding');
      } else {
        setMessageIndex(messageIndex + 1);
      }
    }, 1500);
    return () => clearTimeout(timer);
  }, [messageIndex]);
こう書くと、ここでsetIntervalとclearのプロセスが必要なく繰り返されていますが、動作方式はsetTimeoutとあまり変わらないようなので、以下のように修正しました.
useEffect(() => {
    setTimeout(() => {
      if (messages.length - 1 === messageIndex) {
        router.push('/onboarding');
      } else {
        setMessageIndex(messageIndex + 1);
      }
    }, 1500);
  }, [messageIndex]);
こうして最終的に虫たちが望む結果が実現したが、解決策はあまり満足していない.このコードがこのようにしている間にsettimeout()と同じ動作ではなくsetInterval()で動作しなければならない場合,一瞬ごとにクリアされず,予想される動作に従う.そこで,messageIndexを依存配列に入れない方法を見つけて,この状況を解決した.
これは、最新のmessageIndex値ではなく、古いmessageIndex値(すなわち0)がコンソールに印刷され続ける理由です.これは、messageIndex値がモジュールにロックされているためです.これらの古い閉パケット問題を回避する方法を見つけた後,refを用いてこれらの問題を回避できると考え,以下のコードを修正した.
const latestValue = useRef(messageIndex);

useEffect(() => {
    let timer = setInterval(() => {
      console.log(latestValue.current);
      if (messages.length - 1 === latestValue.current) {
        router.push('/onboarding');
      } else {
        setMessageIndex((prev) => {
          latestValue.current = prev + 1;
          return prev + 1;
        });
      }
    }, 1500);
    return () => clearTimeout(timer);
  }, []);
現在のような古い状態ではなくrefによって変数を管理することで、キャビネットに閉じ込められた変数を救い、自分の意思で動作させることができる.
最新のstate値で所望の値に容易にアクセスできるように,この部分をhookに分割してコードを整理する.
  • useLatestState.ts
  • import { Dispatch, MutableRefObject, SetStateAction, useRef, useState } from 'react';
    
    function useLatestState<T>(initData: T): [T, Dispatch<SetStateAction<T>>, MutableRefObject<T>] {
      const [state, setState] = useState<T>(initData);
      const latestState = useRef(state);
      latestState.current = state;
    
      return [state, setState, latestState];
    }
    
    export default useLatestState;
    const [messageIndex, setMessageIndex, freshMessageIndex] = useLatestState<number>(0);
    
    useEffect(() => {
        let timer = setInterval(() => {
          console.log(freshMessageIndex.current);
          if (messages.length - 1 === freshMessageIndex.current) {
            router.push('/onboarding');
          } else {
            setMessageIndex(freshMessageIndex.current + 1);
          }
        }, 1500);
        return () => clearTimeout(timer);
      }, []);
    このようにしてこのリカバリホストのシャットダウンの問題は解決されたが、このリカバリホストがどのように動作しているのか、なぜこのようなシャットダウンの問題が発生しているのか、不安が残る一方である.これはよく勉強して次の時にまたやります!