useEffect が return ステートメントで状態変数にアクセスできないのはなぜですか? 質問する

useEffect が return ステートメントで状態変数にアクセスできないのはなぜですか? 質問する

useEffect()React 関数がコンポーネントの状態変数にアクセスできない理由がわかりません。ユーザーがアプリでリストの作成を中止し、別のページに移動したときにログを作成しようとしています。ライフサイクル メソッドuseEffect() returnを複製する方法を使用していますcomponentWillUnmount()。助けてもらえますか?

コードサンプル

  let[progress, setProgress] = React.useState(0)

  ... user starts building their listing, causing progress to increment ...

  console.log(`progress outside useEffect: ${progress}`)
  useEffect(() => {
    return () => logAbandonListing()
  }, [])
  const logAbandonListing = () => {
    console.log(`progress inside: ${progress}`)
    if (progress > 0) {
      addToLog(userId)
    }
  }

予想される行動

コードは に到達しaddToLog()、この動作がログに記録されます。

観察された行動

これは、ユーザーがリストに何かを入力してprogress増加させ、その後ページを離れたときに発生します。

  • このuseEffect()メソッドは完璧に動作し、logAbandonListing()関数を実行します
  • 最初のconsole.log()(上記)は、状態useEffectとして0より大きい値を記録します。progress
  • 2 番目は状態console.log()として 0 をログに記録しprogress、コードがステートメントtrueに戻って関数ifに到達できないようにしますaddToLog()

環境

  • Firefox 76.0.1 で実行されている Next.js で構築されたアプリのローカル開発環境
  • ネクストjs v8.1.0
  • 反応v16.8.6

ここで何が起こっているのか理解するために、助けていただけると本当にありがたいです。ありがとうございます。

ベストアンサー1

これは典型的な古いクロージャの問題だと思います。そして、最初は理解するのが難しいです。

依存関係配列が空の場合、useEffect は 1 回だけ実行されます。そして、その 1 回の実行から状態にアクセスします。したがって、この時点では、logAbandonListing 関数からの参照があります。この関数も、この時点で状態にアクセスします。この問題は複数の方法で解決できます。

その 1 つは、依存関係に状態変数を追加することです。

  useEffect(() => {
    return () => logAbandonListing()
  }, [progress])

もう 1 つの解決策は、状態値を参照に設定することです。参照の参照は変更されないため、常に最新の値が表示されます。

let[progress, setProgress] = React.useState(0);
const progressRef = React.createRef();
progressRef.current = progress;

...

  const logAbandonListing = () => {
    console.log(`progress inside: ${progressRef.current}`)
    if (progressRef.current > 0) {
      addToLog(userId)
    }
  }

userId も変更される場合は、依存関係または参照に追加する必要があります。

おすすめ記事