reactjs - React UseState 在 eventListener 中被调用两次
问题描述
我开始在空闲时间学习反应。启动 Hooks 时,两次调用 setState 方法。实时代码位于
https://codesandbox.io/s/elastic-saha-mdwwc?file=/src/App.js
添加按钮工作正常。但是当我按下回车键时,setState 函数被调用了两次。最初的想法是重新呈现内容。但我将 useEffect 依赖项作为空数组。所以没有重新渲染完成,我不知道如何调试它。任何帮助表示赞赏:)
const App = () => {
const [text, setText] = useState('');
const [list, setList] = useState([]);
const addToList = () => {
if (text !== '') {
setList([...list, text]);
setText('');
}
}
const deleteItem = index => {
const deletedList = list.filter((_, i) => i !== index);
setList(deletedList)
}
useEffect(() => {
console.log("Reloaded");
const listener = e => {
if (e.code === 'Enter') {
console.log("event triggered")
setText(text => {
if (text !== '') {
console.log("updating")
setList(a => ([...a, text]));
}
return ''
});
}
}
document.getElementById('textbox').addEventListener('keyup', listener);
console.log('Event registered')
return () => {
document.getElementById('textbox').removeEventListener('keyup', listener);
console.log('Event deregistered')
}
}, [])
return (
<div >
<input type="text" id="textbox" onChange={(e) => setText(e.target.value)} value={text} />
<button id="add" onClick={addToList}> Add</button>
<ul>
{
list.map((a, i) => <li key={i}>{a} <button type="button" onClick={() => deleteItem(i)}>Delete</button></li>)
}
</ul>
</div>
);
}
export default App;
解决方案
我认为这是因为useEffect
在您的代码中:
setText(text => {
if (text !== '') {
console.log("updating")
setList(a => ([...a, text]));
}
return ''
});
将其更改为以下内容:
useEffect(() => {
console.log("Reloaded");
const listener = (e) => {
if (e.code === "Enter") {
console.log("event triggered");
if (text !== "") {
console.log("updating");
setList((a) => [...a, text]);
}
return "";
}
};
document.getElementById("textbox").addEventListener("keydown", listener);
console.log("Event registered");
return () => {
document
.getElementById("textbox")
.removeEventListener("keydown", listener);
console.log("Event deregistered");
};
}, [text]);
或者,
useEffect(() => {
console.log("Reloaded");
const listener = (e) => {
if (e.code === "Enter") {
console.log("event triggered");
if (e.target.value !== "") {
console.log("updating");
setList((a) => [...a, e.target.value]);
}
e.target.value = "";
return "";
}
};
document.getElementById("textbox").addEventListener("keydown", listener);
console.log("Event registered");
return () => {
document
.getElementById("textbox")
.removeEventListener("keydown", listener);
console.log("Event deregistered");
};
});
或者,
这个使用onKeyPress
事件并且只useEffect
在组件安装时运行一次
import React, { useState, useEffect } from "react";
const App = () => {
const [text, setText] = useState("");
const [list, setList] = useState([]);
const addToList = () => {
if (text !== "") {
setList([...list, text]);
setText("");
}
};
const deleteItem = (index) => {
const deletedList = list.filter((_, i) => i !== index);
setList(deletedList);
};
const listener = (e) => {
e.stopPropagation();
if (e.key === "Enter") {
console.log("event triggered");
if (text !== "") {
console.log("updating");
setList((a) => [...a, text]);
}
setText("");
return "";
}
};
// not needed, only here to show it only runs once
useEffect(() => {
console.log("Reloaded");
}, []);
return (
<div>
<input
type="text"
id="textbox"
onChange={(e) => setText(e.target.value)}
onKeyPress={listener}
value={text}
/>
<button id="add" onClick={addToList}>
{" "}
Add
</button>
<ul>
{list.map((a, i) => (
<li key={i}>
{a}{" "}
<button type="button" onClick={() => deleteItem(i)}>
Delete
</button>
</li>
))}
</ul>
</div>
);
};
export default App;
推荐阅读
- entity-framework - EF Core 根据子数据筛选结果
- javascript - 反应路由器参数
- python - 让 Python 将数据输出到 Excel 工作表
- python - 读取 json 文件得到错误 json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
- swift - Swift:从两个不同的按钮调用相同的方法
- c++ - 使用默认构造函数初始化对象的不同方法
- objective-c - Swift 让计算属性转换为 Objective C 语法
- python - 根据条件创建新列
- c - 是否可以在 Swift 中创建一个可以与 C 代码链接和调用的函数?
- c# - QueryAsync 不返回任何 ID 列(自动编号列)