[英]Why can't useEffect access my state variable in a return statement?
我不明白为什么我的useEffect()
React function 无法访问我的组件的 state 变量。 当用户放弃在我们的应用中创建列表并导航到另一个页面时,我正在尝试创建日志。 我正在使用复制componentWillUnmount()
生命周期方法的useEffect()
return
方法。 你能帮我吗?
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()
functionconsole.log()
(在useEffect
上方)记录大于 0 的progress
stateconsole.log()
为progress
state 记录 0,禁用代码为if
语句返回true
并到达addToLog()
function。我真的很感激一些帮助理解这里发生了什么。 谢谢。
我认为这是一个典型的陈旧关闭问题。 而且一开始很难理解。
使用空依赖数组,useEffect 将只运行一次。 它将从那一次运行中访问 state。 所以从这一刻起它就会有来自 logAbandonListing function 的引用。 从这一刻起,这个 function 也将访问 state。 您可以通过多种方式解决问题。
其中之一是将 state 变量添加到您的依赖项中。
useEffect(() => {
return () => logAbandonListing()
}, [progress])
另一种解决方案是将 state 值设置为参考值。 并且 ref 的引用没有改变,所以你总是会看到最新鲜的值。
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 也发生了变化,那么您应该将其添加到依赖项或引用中。
要在useEffect
的返回 function 中的状态当前值中执行某些操作,其中useEffects
依赖项是空数组[]
,您可以使用useReducer
。 这样,您可以避免过时的关闭问题并从useReducer
的dispatch
function 更新 state。
示例是:
import React, { useEffect, useReducer } from "react";
function reducer(state, action) {
switch (action.type) {
case "set":
return action.payload;
case "unMount":
console.log("This note has been closed: " + state); // This note has been closed: 201
break;
default:
throw new Error();
}
}
function NoteEditor({ initialNoteId }) {
const [noteId, dispatch] = useReducer(reducer, initialNoteId);
useEffect(function logBeforeUnMount() {
return () => dispatch({ type: "unMount" });
}, []);
return <div>{noteId}</div>;
}
export default NoteEditor;
有关此答案的更多信息
当您从useEffect
返回 function 时,它的行为类似于componentWillUnmount
所以我认为它只在清理时运行。 您实际上需要调用logAbandonListing
,例如:
useEffect(() => {
logAbandonListing();
}, []);
所以每次组件重新渲染时它都会运行。 您可以在https://reactjs.org/docs/hooks-effect.html上阅读有关useEffect
的更多信息
它写得非常好。
我尝试使用这个沙盒来解释我的答案。
基本上你是从你的 useEffect 回调中返回一个 function 。 但是返回的 function 从未真正调用过,因此它没有实际执行,因此记录了放弃操作。 如果您查看沙箱中的代码,我在之后添加了一个包装器 Parens 和 () 以实际导致调用该方法,从而导致执行 console.log。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.