单击按钮时如何使用 useRef 挂钩关注 Material UI TextField?

Dan*_*bee 6 reactjs material-ui react-hooks

我有一个类似的问题如何将材质 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>
  );
}
Run Code Online (Sandbox Code Playgroud)

Han*_*dev 8

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

() => {
  setDisabled(false);
  inputRef.current.focus();
};
Run Code Online (Sandbox Code Playgroud)

您应该记住这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
Run Code Online (Sandbox Code Playgroud)