我有一个 queryTerm
变量作为 useEffect
Hook 的依赖项。我还在同一个钩子(Hook)中注册了一个 handleKeyPress
事件监听器。
我面临一个问题,当 queryTerm
依赖项更改时,handleKeyPress
监听器中的 queryTerm
值始终落后于新值一步queryTerm
值。
我将如何同步两者?
import React, { useState, useEffect } from 'react'
const Test = () => {
const [queryTerm, setQueryTerm] = useState('')
const handleChange = (event) => {
setQueryTerm(event.target.value)
}
useEffect(() => {
console.log({ outside: queryTerm })
const handleKeyPress = (event) => console.log({ inside: queryTerm })
window.addEventListener('keydown', handleKeyPress)
return () => window.removeEventListener('keydown', handleKeyPress)
}, [queryTerm])
return (
<div className='App'>
<input onChange={handleChange} />
</div>
)
}
export default Test
最佳答案
这里实际上有3个问题:
"keydown"
和"change"
事件按一定顺序发生,因此如果您在第一次记录某些内容,它肯定不会受到第二次的影响- 即使您更改状态并将其记录在同一事件监听器中,日志也不会受到状态更改的影响,因为后者仅在下一次渲染时有效;请参阅The useState set method is not reflecting a change immediately
- 当构建一个在其主体中使用某种状态的回调时,它实际上“嵌入”了该状态的陈旧值作为其闭包;将状态变量视为每个渲染的不同引用(前面的链接也解释了这一点);解决方法包括利用
useRef
hook,不过要看具体情况
就您而言,尚不清楚为什么您需要在"keydown"
上使用您的状态(以及为什么它必须附加到 window
而不是 <input/>
),并期望它反射(reflect) "change"
上发生的状态更改事件?
这可能是一个人为的示例,但实际上,您可以简单地执行以下操作:
const handleChange = (event) => {
setQueryTerm(event.target.value)
// 1. Do everything in the same event handler
// 2. and 3. Use directly the new value
// instead of reading the state that will
// change only on next render
console.log({ inside: event.target.value })
}
关于reactjs - 通过 useEffect 附加的事件监听器中的值始终落后 React State 一步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74870084/