import { useState, useRef, useEffect } from "react";
function App() {
const [message, setMessage] = useState("");
const inpt = useRef();
const handleKeyDown = (e) => {
if (e.key === "Enter") {
handleClick();
}
};
useEffect(() => {
inpt.current.addEventListener("keydown", handleKeyDown);
return () => inpt.current.removeEventListener("keydown", handleKeyDown);
}, []);
function handleClick() {
console.error(message);
}
return (
<>
<div>
<input ref={inpt} type="text" name="" id="" value={message} onChange={(e)=> setMessage(e.target.value)} />
<button onClick={handleClick}>click</button>
</div>
</>
);
}
export default App;
当我点击按钮时,我可以正确记录
message
,但是当我按“Enter”键时,message
记录为初始值""
。
你能帮我理解为什么会发生这种情况以及我应该做什么吗?
由于您在
useEffect
钩子中使用空依赖数组,因此在由于状态更改而重新渲染时,其清理函数将不会被执行,并且 ref
将继续指向陈旧的 input
元素。
为了避免这种情况,您应该添加 message
的 handleKeydown
作为依赖项。
useEffect(() => {
inpt.current.addEventListener("keydown", handleKeyDown);
return () => inpt.current.removeEventListener("keydown", handleKeyDown);
}, [message]);
您需要使
message
成为效果的依赖项,如 Ravi 所说。
const { useEffect, useRef, useState } = React;
function App() {
const [message, setMessage] = useState("");
const inputRef = useRef();
const handleKeyDown = (e) => {
if (e.key === "Enter") {
handleClick();
}
};
useEffect(() => {
inputRef.current.addEventListener("keydown", handleKeyDown);
return () => inputRef.current.removeEventListener("keydown", handleKeyDown);
}, [message]);
function handleClick() {
console.error(`MESSAGE: ${message}`);
}
return (
<React.Fragment>
<div>
<input ref={inputRef} type="text" value={message} onChange={(e)=> setMessage(e.target.value)} />
<button onClick={handleClick}>Click</button>
</div>
</React.Fragment>
);
}
ReactDOM
.createRoot(document.getElementById("root"))
.render(<App />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
我更好的方法是使用表格。
如果您在字段上使用引用,则不需要存储状态!
const { useCallback, useRef } = React;
function App() {
const inputRef = useRef();
const handleSubmit = useCallback((e) => {
e.preventDefault(); // Do not navigate away from current page
console.error(`MESSAGE: ${inputRef.current.value}`);
}, [inputRef]);
return (
<React.Fragment>
<form onSubmit={handleSubmit}>
<input ref={inputRef} type="text" name="message" />
<button type="submit">Submit</button>
</form>
</React.Fragment>
);
}
ReactDOM
.createRoot(document.getElementById("root"))
.render(<App />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>