警告:组件正在将不受控制的输入更改为受控

Warning: A component is changing an uncontrolled input to be controlled

我有一个项目,这个项目是为了运行一家承包建筑公司,我有一个文件,就是公司每张发票的信息,这个文件是一套的字段,但我有这个错误,我不知道原因或如何解决它?

index.js:1 Warning: A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components

此文件显示一组字段

import { getInvoice } from "../../store/invoiceSlice";
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import Grid from "@material-ui/core/Grid";
import TextField from "@material-ui/core/TextField";
import moment from "moment";
import { useTheme } from "@material-ui/core/styles";
import InputAdornment from "@material-ui/core/InputAdornment";
import TodayIcon from "@material-ui/icons/Today";
import { makeStyles } from "@material-ui/core/styles";
import { PDFViewer } from "@react-pdf/renderer";
import { Document, Page } from "react-pdf";

const useStyles = makeStyles((theme) => ({
  root: {
    "& > *": {
      margin: theme.spacing(1),
    },
  },
  input: {
    display: "none",
  },
  button: {
    margin: theme.spacing(1),
    // padding: theme.spacing(4),
  },
}));
const InvoiceDetails = () => {
  const classes = useStyles();
  const theme = useTheme();
  const breakpoint = theme.breakpoints.down("sm");
  const routeParams = useParams();
  const [invoice, setInvoice] = useState([]);

  // const defaultLayoutPluginInstance = defaultLayoutPlugin();

  useEffect(() => {
    getInvoice(routeParams).then((response) => {
      setInvoice(response);
    });
  }, []);

  console.log("invoice url: ", invoice?.file?.url);
  console.log("invoice tara : ", invoice);

  const [numPages, setNumPages] = useState(null);
  const [pageNumber, setPageNumber] = useState(1);

  const onDocumentLoadSuccess = ({ numPages }) => {
    setNumPages(numPages);
  };

  return (
    <>
      <Grid container>
        <Grid item xs={7} sm={7} style={{ height: "100vh", width: "100vh" }}>
          {/* <PDFViewer file={invoice?.file?.url}></PDFViewer> */}
          <Document
            file={invoice?.file?.url}
            onLoadSuccess={onDocumentLoadSuccess}
          >
            <Page pageNumber={pageNumber} />
          </Document>
          <p>
            Page {pageNumber} of {numPages}
          </p>
        </Grid>
        <Grid item xs={5} sm={5} style={{ padding: "3rem" }}>
          <Grid item>
            <h1 style={{ fontWeight: "bold" }}>Invoice Details</h1>
          </Grid>

          <Grid item style={{ marginTop: "3rem", marginBottom: "2rem" }}>
            <Grid item style={{ marginBottom: 10 }}>
              <h3>From</h3>
            </Grid>
            <Grid item>
              <h3>{invoice?.submittedBy?.name}</h3>
            </Grid>
            <Grid item>
              <h3>{invoice?.submittedBy?.email}</h3>
            </Grid>
          </Grid>

          <Grid item>
            <Grid container item direction={breakpoint ? "row" : "column"}>
              <Grid
                container
                item
                xs={3}
                sm={3}
                direction="row"
                justifyContent="flex-start"
                alignItems="center"
              >
                <h3>Invoice ID</h3>
              </Grid>
              <Grid item xs={9} sm={9}>
                <TextField
                  className="mt-8 mb-16"
                  id="outlined-size-normal"
                  value={invoice.id}
                  variant="outlined"
                  fullWidth
                />
              </Grid>
            </Grid>

            <Grid container item direction={breakpoint ? "row" : "column"}>
              <Grid
                container
                item
                xs={3}
                sm={3}
                direction="row"
                justifyContent="flex-start"
                alignItems="center"
              >
                <h3>Issue Date</h3>
              </Grid>
              <Grid item xs={9} sm={9}>
                <TextField
                  className="mt-8 mb-16"
                  id="outlined-size-normal"
                  value={moment(moment.utc(invoice.issueDate).toDate())
                    .local()
                    .format("YYYY-MM-DD HH:mm:ss")}
                  variant="outlined"
                  InputProps={{
                    endAdornment: (
                      <InputAdornment position="start">
                        <TodayIcon />
                      </InputAdornment>
                    ),
                  }}
                  fullWidth
                />
              </Grid>
            </Grid>

            <Grid container item direction={breakpoint ? "row" : "column"}>
              <Grid
                container
                item
                xs={3}
                sm={3}
                direction="row"
                justifyContent="flex-start"
                alignItems="center"
              >
                <h3>Due Date</h3>
              </Grid>
              <Grid item xs={9} sm={9}>
                <TextField
                  className="mt-8 mb-16"
                  id="outlined-size-normal"
                  value={moment(moment.utc(invoice.dueDate).toDate())
                    .local()
                    .format("YYYY-MM-DD HH:mm:ss")}
                  variant="outlined"
                  InputProps={{
                    endAdornment: (
                      <InputAdornment position="start">
                        <TodayIcon />
                      </InputAdornment>
                    ),
                  }}
                  fullWidth
                />
              </Grid>
            </Grid>

            <Grid container item direction={breakpoint ? "row" : "column"}>
              <Grid
                container
                item
                xs={3}
                sm={3}
                direction="row"
                justifyContent="flex-start"
                alignItems="center"
              >
                <h3>Net Amount</h3>
              </Grid>
              <Grid item xs={9} sm={9}>
                <TextField
                  className="mt-8 mb-16"
                  id="outlined-size-normal"
                  value={invoice.netAmount}
                  variant="outlined"
                  fullWidth
                />
              </Grid>
            </Grid>

            <Grid container item direction={breakpoint ? "row" : "column"}>
              <Grid
                container
                item
                xs={3}
                sm={3}
                direction="row"
                justifyContent="flex-start"
                alignItems="center"
              >
                <h3>Tax Number</h3>
              </Grid>
              <Grid item xs={9} sm={9}>
                <TextField
                  className="mt-8 mb-16"
                  id="outlined-size-normal"
                  value={invoice.taxNumber}
                  variant="outlined"
                  fullWidth
                />
              </Grid>
            </Grid>

            <Grid container item direction={breakpoint ? "row" : "column"}>
              <Grid
                container
                item
                xs={3}
                sm={3}
                direction="row"
                justifyContent="flex-start"
                alignItems="center"
              >
                <h3>Gross Amount</h3>
              </Grid>
              <Grid item xs={9} sm={9}>
                <TextField
                  className="mt-8 mb-16"
                  // label="Size"
                  id="outlined-size-normal"
                  value={invoice.grossAmount}
                  variant="outlined"
                  fullWidth
                />
              </Grid>
            </Grid>
          </Grid>
        </Grid>
      </Grid>
    </>
  );
};

export default InvoiceDetails;

我认为这是由您的 invoice 以 [] 开头引起的。因此,像 invoice.id 这样的字段最初将是 null 并且当您最终从 API 获取数据并将数据设置为 invoice 时,invoice.id 变得不为空,因此声明:This is likely caused by the value changing from undefined to a defined value

要解决警告,您可能必须在 useState 中声明发票的所有属性。例如:

useState({
    id: "",
    issueDate: "",
    dueDate: "",
})

或者,如果您不打算控制输入,则可能对 TextFields 使用 defaultValue 而不是 value。有什么不同?对于 value,您必须提供 onChange.

如果您将组件的 value prop 设置为未定义,它们将变得不受控制。这是一个例子:

<TextField
 className="mt-8 mb-16"
 id="outlined-size-normal"
 value={invoice.id} // invoice.id is initially undefined
 variant="outlined"
 fullWidth
/>

然后,一旦您 运行 setInvoice() 定义了这些值,组件就会受到控制。 要使它们始终受控,您可以做的是像这样设置适当的状态初始值:

const [invoice, setInvoice] = useState({ // Note that the initial value is an object and not an array
 id: "",
 issueDate: null,
 netAmount: 0,
 taxNumber: 0,
 grossAmount: 0
});

或者您可以对每个组件执行此操作:

<TextField
 className="mt-8 mb-16"
 id="outlined-size-normal"
 value={invoice.id || ""}
 variant="outlined"
 fullWidth
/>