所以我有这个反应功能组件:
export default function Login() {
const [loginData, setLoginData] = useState<Credentials>({ email: "", password: "" })
useEffect(() => {
document.addEventListener('keydown', handleKeyDown)
return () =>
document.removeEventListener('keydown', handleKeyDown)
}, [])
function handleKeyDown(event: any) {
if (event.key === "Enter")
confirm()
}
function confirm() {
httpPut<Credentials, void>("user/login", loginData).then(
res => {
var authorization = res.headers.authorization
const parsed = jwt_decode(authorization)
console.log(parsed)
},
err => {
console.log(err)
}
)
}
return ...
}
我遇到了一些奇怪的行为,至少据我所知。我为 enter 键添加事件侦听器的 useEffect 正在保存 loginData 的状态。我的意思是,如果我填写输入并单击按钮,一切正常,但是当我单击回车键时,(我在我的 axios 请求中放置了一个 console.log 以便它记录数据)它来了{ email: "", password: "" }
。现在,通过尝试 arround,我设法通过添加 loginData 作为 useEffect 的依赖项来修复它,如下所示:
useEffect(() => {
document.addEventListener('keydown', handleKeyDown)
return () =>
document.removeEventListener('keydown', handleKeyDown)
}, [loginData])
但这应该发生吗?这不是我第一次使用 React,而且我总是在 useEffect 中添加没有依赖关系的侦听器。对我来说,这似乎很奇怪,它有点“保存”事件侦听器本身的 loginData 状态。知道为什么会这样吗?或者即使它应该这样做?我让它工作,但我想知道为什么。
你看到了一个陈旧的闭包(一个像 React hooks 一样古老的故事)。
handleKeyDown
。handleKeyDown
结束于版本 1 confirm
。confirm
关闭了 的初始状态loginData
。(因为你应该替换诸如对象或数组之类的状态原子,而不是在内部改变它们以便 React 可以看到更改,所以原始对象仍然是封闭的)。loginData
发生变化时,会创建新版本的confirm
和handleKeyDown
1. 这就是为什么该事件处理程序看到原始版本loginData
以及为什么设置loginData
为依赖项可以解决问题(因为它会导致新版本handleKeyDown
和confirm
用于事件)。您的选择或多或少是:
loginData
你一样依赖效果。这将导致无关的事件处理程序取消订阅/订阅周期,但这些可能不是性能问题。useCallback
编辑,因此它们仅在必要时更新。不过,这或多或少是上述情况。loginData
(例如useLatest
hook)的最新状态,并在您的函数中使用该装箱的 ref confirm
,即loginDataRef.current
. 由于confirm
仅关闭 ref (这是一个包含可变引用的“框”)而不是 over loginDataRef.current
,因此访问current
将始终获得最新状态。confirm
像上面一样,使用ref 将最新版本confirmRef.current()
的confirm
.本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句