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

Time:04-22

I have a project and this project is in order to run a contracting and construction company, and I have a file, which is the information for each of the company’s invoices, and this file is a set of fields, but I had this error and I did not know the cause or how can i solve it?

 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

This file displays a set of fields

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}
            onl oadSuccess={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;

CodePudding user response:

If you set as undefined the value prop of your components they become uncontrolled. This is an example:

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

Then, once you run the setInvoice() to define those values the components become controlled. What you can do to make them always controlled is to set a proper initial value of the state like this:

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
});

Or alternatively you can do this to each of your components:

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

CodePudding user response:

I believe it's caused by your invoice starting as []. Therefore, fields like invoice.id will be initially null and when u finally fetch data from API & set data into invoice, invoice.id became not null, hence the statement: This is likely caused by the value changing from undefined to a defined value

To solve the warning, you might have to declare all the properties of the invoice in useState. Eg:

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

or perhaps, use defaultValue instead of value for the TextFields if u don't intend to control the inputs. What's the difference? with value, you have to supply onChange.

  • Related