英文:
Accesing form input element onChange
问题
我想要能够在keydown
和鼠标点击事件中都能选择radio
按钮。但是我在同一个函数中无法访问keydown
事件和鼠标点击事件的两个event
参数。因此,我无法在keydown
事件中更新状态来存储选择的值,但在鼠标点击事件中可以访问输入事件参数。
以下是代码:
import { useState, useEffect, useRef } from "react";
import { useLocation } from "react-router-dom";
import { englishQuestions } from "../questions/englishQ";
const English = () => {
// ... 省略了一些代码
// 这是我无法访问`keydown`事件的`onChange`函数
const handleChange = (e: any) => {
// ... 省略了一些处理逻辑
};
const submit = (e: any) => {
e.preventDefault();
// ... 省略了一些提交逻辑
};
// 这里是事件监听器的调用
useEffect(() => {
document.body.addEventListener("keydown", handleChange);
}, [input]);
return (
<>
<div className="bg-gray-200 mx-auto my-10 w-3/4 p-10 shadow-sm shadow-gray-600 rounded-lg">
<form onSubmit={submit} className="mb-10">
{englishQuestions.map((question) => {
// ... 省略了一些循环逻辑
})}
<div className="flex justify-center">
<button
type="submit"
name="submit"
className="btnExam p-3 mx-auto cursor-pointer"
>
Submit
</button>
</div>
</form>
</div>
</>
);
};
export default English;
请注意,上面的代码只是提取了与翻译请求相关的部分。如果您需要更多的帮助或解释,请随时提问。
英文:
I want to be able to select a radio
button onChange viakeydown
and mouse click. But I am having trouble accessing both event
parameters of the on keydown
and on mouse click in the same function. So can't update my state to store selected value on keydown
but it works on mouse click because I can access the input event parameter on mouse click.
Here is the code.
import { useState, useEffect, useRef } from "react";
import { useLocation } from "react-router-dom";
import { englishQuestions } from "../questions/englishQ";
const English = () => {
const theRef = useRef();
const { state } = useLocation();
const { user } = state;
const [input, setInputs] = useState<{ [key: string]: string }[]>([]);
const [answersSelected, setAnswersSelected] = useState({});
const [selected, setSelected] = useState<{ [key: string]: boolean }>({});
const [submitted, setSubmitted] = useState(false);
const [keyCode, setKeyCode] = useState("");
var index1 = 0;
const answers = englishQuestions.map((items, index) => items.answer);
//This is the `onChange` `function` from which I can't access `keydown` event
const handleChange = (e: any) => {
const numbers = /\d+/g;
switch (e.code) {
case "keyA":
setKeyCode("keyA");
const { value, name } = e.target;
const currentQuestionNumber = name.slice(name.indexOf("englishQ"), 10);
const currentQuestion = name.slice(name.indexOf(":") + 2);
const currentArrayIndex = name.match(numbers)[0] - 1;
if (answers[currentArrayIndex] === value) {
setInputs([
...input,
{
questionNumber: currentQuestionNumber.trim(),
question: currentQuestion,
answer: value,
status: "correct",
marks: "2",
},
]);
setAnswersSelected({ ...answersSelected, [name]: value });
} else {
setInputs([
...input,
{
questionNumber: currentQuestionNumber.trim(),
question: currentQuestion,
answer: value,
status: "wrong",
marks: "0",
},
]);
setAnswersSelected({ ...answersSelected, [name]: value });
}
//detect if an answer was selected
setSelected({ ...selected, [currentArrayIndex + 1]: true });
//convert the answered object keys into an array
const submittedKeys = Object.keys(selected);
//check if all answers were selected
const checkSelelction = submittedKeys.filter(
(key, index) => selected[key] === true
);
if (checkSelelction.length + 1 >= 10) {
setAllSelected(true);
} else {
setAllSelected(false);
}
break;
case "keyB":
setKeyCode("keyB");
break;
case "keyC":
setKeyCode("keyC");
break;
case "keyD":
setKeyCode("keyD");
break;
default:
setKeyCode("");
}
setSelectedValue([...selectedValue, { theSelectedValue: e.target.value }]);
localStorage.setItem("theSelectedValue", JSON.stringify(selectedValue));
console.log(localStorage.getItem("theSelectedValue") as string);
const { value, name } = e.target;
const currentQuestionNumber = name.slice(name.indexOf("englishQ"), 10);
const currentQuestion = name.slice(name.indexOf(":") + 2);
const currentArrayIndex = name.match(numbers)[0] - 1;
if (answers[currentArrayIndex] === value) {
setInputs([
...input,
{
questionNumber: currentQuestionNumber.trim(),
question: currentQuestion,
answer: value,
status: "correct",
marks: "2",
},
]);
setAnswersSelected({ ...answersSelected, [name]: value });
} else {
setInputs([
...input,
{
questionNumber: currentQuestionNumber.trim(),
question: currentQuestion,
answer: value,
status: "wrong",
marks: "0",
},
]);
setAnswersSelected({ ...answersSelected, [name]: value });
}
//detect if an answer was selected
setSelected({ ...selected, [currentArrayIndex + 1]: true });
//convert the answered object keys into an array
const submittedKeys = Object.keys(selected);
//check if all answers were selected
const checkSelelction = submittedKeys.filter(
(key, index) => selected[key] === true
);
if (checkSelelction.length + 1 >= 10) {
setAllSelected(true);
} else {
setAllSelected(false);
}
};
const submit = (e: any) => {
e.preventDefault();
setSubmitted(true);
localStorage.setItem("studentId", JSON.stringify(user.studentId));
localStorage.setItem("englishSubmitted", "true");
localStorage.setItem("englishAnswers", JSON.stringify(input));
};
//Here is the call to the event listener
useEffect(() => {
document.body.addEventListener("keydown", handleChange);
}, [input]);
return (
<>
<div className="bg-gray-200 mx-auto my-10 w-3/4 p-10 shadow-sm shadow-gray-600 rounded-lg">
<form onSubmit={submit} className="mb-10">
{englishQuestions.map((question) => {
index1 = index1 + 1;
return (
<div
key={index1}
className={index1 === theValue.first ? "" : "hidden"}
>
<h3>
<span className={submitted ? "text-gray-400" : "font-bold"}>
Q {index1}:
</span>{" "}
{question.start}{" "}
<span className="underline">{question.theWord}</span>{" "}
{question.end}
</h3>
{question.options.map((item, index) => {
return (
<div className="mb-3" key={index}>
<label htmlFor="">a: </label>
<input
id="a"
type="radio"
name={`englishQ${index1} : ${question.start} ${question.theWord} ${question.end}`}
value={item.a}
onChange={handleChange}
disabled={submitted ? true : false}
checked={keyCode === "KeyA" ? true : false}
/>
<label htmlFor=""> {item.a}</label>
<br />
<label htmlFor="">b: </label>
<input
id="b"
type="radio"
name={`englishQ${index1} : ${question.start} ${question.theWord} ${question.end}`}
value={item.b}
onChange={handleChange}
disabled={submitted ? true : false}
checked={keyCode === "KeyB" ? true : false}
/>
<label htmlFor=""> {item.b}</label>
<br />
<label htmlFor="">c: </label>
<input
id="c"
type="radio"
name={`englishQ${index1} : ${question.start} ${question.theWord} ${question.end}`}
value={item.c}
onChange={handleChange}
disabled={submitted ? true : false}
checked={keyCode === "KeyC" ? true : false}
/>
<label htmlFor=""> {item.c}</label>
<br />
<label htmlFor="">d: </label>
<input
id="d"
type="radio"
name={`englishQ${index1} : ${question.start} ${question.theWord} ${question.end}`}
value={item.d}
onChange={handleChange}
disabled={submitted ? true : false}
checked={keyCode === "KeyD" ? true : false}
/>
<label htmlFor=""> {item.d}</label>
</div>
);
})}
</div>
);
})}
<div className="flex justify-center">
<button
type="submit"
name="submit"
className="btnExam p-3 mx-auto cursor-pointer"
>
Submit
</button>
</div>
</form>
</div>
</>
);
};
export default English;
答案1
得分: 1
你应该在输入框上使用onKeyDown
属性,而不是onChange
来处理按键操作。
例如:
<input onKeyDown={handleKeyPress} />
然后,你可以使用onClick
和onKeyDown
来执行你想要的操作。
英文:
You should use the onKeyDown
property on the input instead of the onChange
to handle the key press.
E.g
<input onKeyDown={handleKeyPress} />
...
const handleKeyPress = (e) => { if (e.key === 'Backspace') ... }
Then you can use the onClick and onKeyDown to do whatever you want.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论