【发布时间】:2022-01-14 13:41:00
【问题描述】:
我遇到了这种我无法解释的奇怪行为。代码的沙箱可以在here找到。
我正在尝试通过按 DEL 或 BACKSPACE 添加重置 readOnly 字段的可能性,但它不起作用。在尝试重现该问题时,我可以在按下按钮时重置它,但在键盘上打字时则不行;为什么?
import React, { useCallback, useState } from "react";
import Button from "@mui/material/Button";
import TextField from "@mui/material/TextField";
import AdapterDayjs from "@mui/lab/AdapterDayjs";
import LocalizationProvider from "@mui/lab/LocalizationProvider";
import DatePicker from "@mui/lab/DatePicker";
import Typography from "@mui/material/Typography";
import frLocaleDate from "dayjs/locale/fr";
export default function BasicDatePicker() {
const [value, setValue] = useState(null);
const [message, setMessage] = useState("");
const handleChanged = useCallback((newValue) => {
setMessage("Value changed to " + newValue);
setValue(newValue);
}, []);
const handleInputKeyDown = useCallback((event) => {
if (event.keyCode === 8 || event.keyCode === 46) {
setMessage("Reset through handleInputKeyDown");
setValue(null);
}
}, []);
const handleReset = useCallback(() => {
setMessage("Reset through handleReset");
setValue(null);
}, []);
return (
<LocalizationProvider dateAdapter={AdapterDayjs} locale={frLocaleDate}>
<Typography>Try pressing DEL or BACKSPACE to clear</Typography>
<DatePicker
clearable
showTodayButton
label="Basic example"
inputFormat="LL"
value={value}
onChange={handleChanged}
renderInput={({ InputProps, inputProps, ...props }) => (
<TextField
fullWidth
margin="dense"
size="small"
onKeyDown={handleInputKeyDown}
InputProps={{ ...InputProps }}
inputProps={{ ...inputProps, readOnly: true, placeholder: "" }}
{...props}
/>
)}
/>
<Button onClick={handleReset}>Reset</Button>
<Typography>
Debug: <pre>{message}</pre>
</Typography>
<Typography>
Current value: <pre>{JSON.stringify(value)}</pre>
</Typography>
</LocalizationProvider>
);
}
我尝试在handleInputKeyDown函数内部延迟setValue(null),但是即使值为null,输入仍然显示一个值。
** 更新**
仅当字段具有焦点时才会出现此问题。如果我像这样更改handleInputKeyDown,请按 DEL 并单击远离输入字段(即使其失去焦点),然后该字段在 2 秒后重置(当 setTimeout 调用处理函数)。
const handleInputKeyDown = useCallback((event) => {
if (event.keyCode === 8 || event.keyCode === 46) {
setTimeout(() => {
setMessage("Reset through handleInputKeyDown");
setValue(null);
}, 2000);
}
}, []);
我尝试给DatePicker组件添加一个引用,然后调用ref.current.blur();,但是不起作用,并且元素没有失去焦点。
** 更新 2 **
按照 Emanuele Scarabattoli 的回答和解释,这似乎也适用于我的特殊情况:
const handleInputKeyDown = useCallback((event) => {
//event.preventDefault();
if (event.keyCode === 8 || event.keyCode === 46) {
setTimeout(() => {
event.target.blur(); // blur outside the scope of keyDown
setMessage("Reset through handleInputKeyDown");
setValue(null);
}, 0);
}
}, []);
这引发了另一个问题:当字段获得焦点时,更改值不会更新显示。当用户选择字段时,这是有问题的,但程序以编程方式更新它;值得到更新,但用户没有更改的反馈。
【问题讨论】:
-
我之前提供了一个错误的答案(然后被删除),现在我完全改变了它,它正在工作(至少通过改变你提供的 sn-p 中的代码)。
-
关于上次更新,我的建议是有条件地使用
blur和preventDefault,具体取决于keyCode。让我知道这是否可行,以便我更新答案。 -
似乎这两种解决方案(使用
event.preventDefault()和延迟event.target.blur())似乎都适用于 DEL 和 BACKSPACE 所以没关系暂且。这两个问题都已在 Github 上发布(未提供,因此我没有交叉发布)
标签: javascript reactjs material-ui