useState Hook 在事件监听器中不起作用
useState Hook not working inside event listener
setter 使用 useState 的函数在事件侦听器函数中不工作。
- 访问沙箱:https://codesandbox.io/s/mystifying-austin-e9zgh
- 点击搜索框,将出现一个建议下拉列表
- 按下键,高亮显示下一项
- 再次按下键不起作用[问题],预期行为:向下键应指向下一项
问题陈述:使用“Down/Up”键可访问性制定搜索建议。
实施:
- 创建一个搜索栏组件。
<input
style={{ outline: "none" }}
placeholder="Search Here"
className="w-full text-gray-800"
onClick={() => {
setShowSuggestion(true);
document.addEventListener("keydown", escFunction, false);
}}
onChange={(event) => setTitle(event.target.value)}
value={value}
/>
- 创建建议组件。
<div
className={
!showSuggestion
? "hidden"
: "flex flex-row border border-gray-300 border-t-0 mx-auto w-3/4 space-x-4"
}
>
<ul className="w-full">
{people.map((person) => (
<li
key={person.id}
className={cursor === person.id ? "bg-red-500" : ""}
>
{person.name}
</li>
))}
</ul>
</div>
- 单击搜索栏时添加事件列表器以检查按键
- 在关键事件 ==“向下箭头键”上,设置选定的推荐 = 列表中的下一项。
function escFunction(event) {
if (event.keyCode === 27) {
document.removeEventListener("keydown", escFunction);
setShowSuggestion(false);
}
if (event.keyCode === 40) {
const nextId = cursor + 1;
setCursor(nextId); //---------------> this line not setting the value
setTitle(people[nextId].name);
}
}
**问题:**
按键事件被触发,但是setter功能在第一次点击后不起作用
不应将事件侦听器添加到文档中,而应将其添加到输入键按下事件中。在访问其名称之前,还要检查人员对象的密钥是否可用 - people[nextId].name
。这应该可以解决您的问题:
<input
style={{ outline: "none" }}
placeholder="Search Here"
className="w-full text-gray-800"
onClick={() => {
setShowSuggestion(true);
}}
onKeyDown={escFunction}
onChange={(event) => setTitle(event.target.value)}
value={value}
/>
cursor
的值(更新值)在执行 escFunction 期间不可用。
为了访问必须将其转换为 setCursor(currentId => currentId + 1);
或
的值
setCursor(currentId =>{
// do pre processing
return cursor+1
})
如评论中所暗示:
传递回调允许您访问当前状态值。您的代码在上次渲染子项时围绕状态值创建一个闭包。
cursor从状态里面那个闭包函数一直是初始值,因为闭包函数
setter 使用 useState 的函数在事件侦听器函数中不工作。
- 访问沙箱:https://codesandbox.io/s/mystifying-austin-e9zgh
- 点击搜索框,将出现一个建议下拉列表
- 按下键,高亮显示下一项
- 再次按下键不起作用[问题],预期行为:向下键应指向下一项
问题陈述:使用“Down/Up”键可访问性制定搜索建议。
实施:
- 创建一个搜索栏组件。
<input
style={{ outline: "none" }}
placeholder="Search Here"
className="w-full text-gray-800"
onClick={() => {
setShowSuggestion(true);
document.addEventListener("keydown", escFunction, false);
}}
onChange={(event) => setTitle(event.target.value)}
value={value}
/>
- 创建建议组件。
<div
className={
!showSuggestion
? "hidden"
: "flex flex-row border border-gray-300 border-t-0 mx-auto w-3/4 space-x-4"
}
>
<ul className="w-full">
{people.map((person) => (
<li
key={person.id}
className={cursor === person.id ? "bg-red-500" : ""}
>
{person.name}
</li>
))}
</ul>
</div>
- 单击搜索栏时添加事件列表器以检查按键
- 在关键事件 ==“向下箭头键”上,设置选定的推荐 = 列表中的下一项。
function escFunction(event) {
if (event.keyCode === 27) {
document.removeEventListener("keydown", escFunction);
setShowSuggestion(false);
}
if (event.keyCode === 40) {
const nextId = cursor + 1;
setCursor(nextId); //---------------> this line not setting the value
setTitle(people[nextId].name);
}
}
**问题:** 按键事件被触发,但是setter功能在第一次点击后不起作用
不应将事件侦听器添加到文档中,而应将其添加到输入键按下事件中。在访问其名称之前,还要检查人员对象的密钥是否可用 - people[nextId].name
。这应该可以解决您的问题:
<input
style={{ outline: "none" }}
placeholder="Search Here"
className="w-full text-gray-800"
onClick={() => {
setShowSuggestion(true);
}}
onKeyDown={escFunction}
onChange={(event) => setTitle(event.target.value)}
value={value}
/>
cursor
的值(更新值)在执行 escFunction 期间不可用。
为了访问必须将其转换为 setCursor(currentId => currentId + 1);
或
setCursor(currentId =>{
// do pre processing
return cursor+1
})
如评论中所暗示:
传递回调允许您访问当前状态值。您的代码在上次渲染子项时围绕状态值创建一个闭包。
cursor从状态里面那个闭包函数一直是初始值,因为闭包函数