单击按钮时,如何使用useRef钩子专注于Material UI TextField?



我有一个类似于如何在按钮单击时聚焦材质 UI 文本字段的问题? 但我无法用提供的答案解决问题。

这是代码。基本上,所有文本字段都被禁用。单击编辑配置文件按钮时,它会将帐户名称的disabled状态设置为false,我想专注于该特定字段。我正在使用useRef钩子来引用该字段,但它不起作用。只有当我单击该按钮两次时,它才会起作用。

import React, { useState, useEffect, useRef } from "react";
import Avatar from "@material-ui/core/Avatar";
import Button from "@material-ui/core/Button";
import CssBaseline from "@material-ui/core/CssBaseline";
import TextField from "@material-ui/core/TextField";
import Grid from "@material-ui/core/Grid";
import PermContactCalendarIcon from "@material-ui/icons/PermContactCalendar";
import Typography from "@material-ui/core/Typography";
import { makeStyles } from "@material-ui/core/styles";
import Container from "@material-ui/core/Container";
import Paper from "@material-ui/core/Paper";
const useStyles = makeStyles((theme) => ({
paper: {
marginTop: theme.spacing(3),
padding: theme.spacing(5),
display: "flex",
flexDirection: "column",
alignItems: "center",
},
avatar: {
margin: theme.spacing(1),
backgroundColor: theme.palette.secondary.main,
},
form: {
width: "100%", // Fix IE 11 issue.
marginTop: theme.spacing(3),
},
submit: {
margin: theme.spacing(3, 0, 2),
},
fixedHeight: {
height: 1000,
},
button: {
marginTop: theme.spacing(3),
marginRight: theme.spacing(3),
},
}));
export default function AccountPage({ userdata }) {
const classes = useStyles();
const [accountName, setAccountName] = useState("");
const [disabled, setDisabled] = useState(true);
const inputRef = useRef(null);
const handleOnChange = (e) => {
if (e.target.name === "accountname") {
setAccountName(e.target.value);
}
};
return (
<Container component="main">
<CssBaseline />
<Paper>
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<PermContactCalendarIcon />
</Avatar>
<Typography component="h1" variant="h5">
Account & User Settings
</Typography>
<form className={classes.form} noValidate>
<Grid
container
direction="column"
justify="center"
alignItems="stretch"
spacing={2}
>
<Grid item xs={12}>
<Typography color="primary" display="inline" noWrap>
Account Name :
</Typography>
</Grid>
<Grid item xs={12}>
<TextField
name="accountname"
variant="outlined"
fullWidth
//   autoFocus
onChange={handleOnChange}
disabled={disabled}
value={accountName}
inputRef={inputRef}
/>
</Grid>
<Grid item xs={12}>
<Typography color="primary" display="inline" noWrap>
E-mail Address :
</Typography>
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
fullWidth
value={userdata.email}
type="email"
name="email"
disabled={true}
//   onChange={handleOnChange}
/>
</Grid>
<Grid item xs={12}>
<Typography color="primary" display="inline" noWrap>
Account ID :
</Typography>
</Grid>
<Grid item xs={12}>
<TextField
variant="outlined"
fullWidth
name="id"
value={userdata._id}
type="text"
disabled={true}
//   onChange={handleOnChange}
/>
</Grid>
</Grid>
<Button
variant="contained"
color="primary"
className={(classes.submit, classes.button)}
onClick={() => {
setDisabled(false);
inputRef.current.focus();
}}
>
Edit Profile
</Button>
<Button
//   type="submit"
variant="contained"
color="primary"
className={(classes.submit, classes.button)}
onClick={() => {
setDisabled(true);
}}
>
Save Changes
</Button>
</form>
</div>
</Paper>
</Container>
);
}

问题出在"编辑"按钮的 onClick 事件处理程序中:

() => {
setDisabled(false);
inputRef.current.focus();
};

您应该记住,setState是异步的。以下是 React 文档中的一段话:

setState 函数用于更新状态。它接受一个新的 状态值,并将组件的重新呈现排队

换句话说,React 承诺disabled将在未来某个时候设置为false,但可能不会在执行行inputRef.current.focus()时设置。

所以你想做的是问 React:disabled设置为false时,聚焦一个元素。这就是useEffect钩子的用途 - 它可以让您执行副作用。因此,与其将inputRef.current.focus()放在setDisabled(false)之后,不如设置一个useEffect钩子,如下所示:

useEffect(() => {
if (!disabled) {
inputRef.current.focus();
}
}, [disabled]); // Only run the function if disabled changes

最新更新