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 も変更される場合は、依存関係または参照に追加する必要があります。