简体   繁体   中英

MUI: A component is changing the uncontrolled value state of Select to be controlled

I'm trying to create a edit form to edit data from database by id. I tried this:

    import React, {FormEvent, useEffect, useState} from "react";
    import TextField from "@material-ui/core/TextField";
    import { createStyles, makeStyles, Theme } from "@material-ui/core/styles";
    import {
      TicketFullDTO,
      TicketStatusTypesDTO,
    } from "../../service/support/types";
    import {
      getTicket,
      getTicketStatusTypes,
      updateTicket,
    } from "../../service/support";
    import { useHistory, useParams } from "react-router-dom";
    import InputLabel from "@mui/material/InputLabel";
    import Select from "@mui/material/Select";
    import MenuItem from "@mui/material/MenuItem";
    import { FormControl } from "@mui/material";
    import { Moment } from "moment";
    import { RouteParams } from "../../service/utils";
       
    export default function TicketProfile(props: any) {
      const classes = useStyles();
      let history = useHistory();
      let requestParams = useParams<RouteParams>();

      const [status, setStatus] = useState<string>("");
      const [submitDate, setSubmitDate] = useState<Moment | null>(null);
      const [ticket, setTicket] = useState<TicketFullDTO>();
    
      const formSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
        e.preventDefault();
        console.log(e);

        updateTicket(requestParams.id, data)
          .then(({ data }) => {
            console.log(data.title);
            history.replace("/support");
          })
          .catch((err) => {
            console.log(err);
          });
      };
    
      const [ticketCategoriesList, setTicketCategoriesList] = useState<
        TicketCategoryTypesDTO[]
      >([]);
      const [ticket, setTicket] = useState<TicketFullDTO>();
            
      const getSingleTicket = async () => {
        getTicket(requestParams.id)
          .then(({ data }) => {
            setTicket(data);
          })
          .catch((error) => {
            console.error(error);
          });
      };
    
      const [ticketStatusList, setTicketStatusList] = useState<
        TicketStatusTypesDTO[]
      >([]);
    
      useEffect(() => {
        ticketStatusData();
        getSingleTicket();
      }, []);
    
      const ticketStatusData = async () => {
        getTicketStatusTypes()
          .then((resp) => {
            setTicketStatusList(resp.data);
          })
          .catch((error) => {
            console.error(error);
          });
      };
    
      return (
        <Container>
            <form onSubmit={onSubmit}>

                          .........

                          <TextField
                            value={ticket?.title}
                            id="title"                                             
                            onChange={({ target: { value } }) => {
                              setTicket({ ...ticket, title: value });
                            }}
                          />

                          .........

                          <FormControl>
                            <TextField
                              label="Submit Date"
                              id="submit-date"
                              type="date"
                              defaultValue={ticket?.submitDate}                             
                              //@ts-ignore
                              onInput={(e) => setSubmitDate(e.target.value)}
                            />
                          </FormControl>
                       
                          ..........

                            <Select
                              labelId="status-label"
                              id="status-helper"
                              value={ticket?.status}
                              onChange={(e) => setStatus(e.target.value)}
                              required
                            >
                              {ticketStatusList.map((element) => (
                                <MenuItem value={element.code}>
                                  {element.name}
                                </MenuItem>
                              ))}
                            </Select>
                          </FormControl>

                         ...........
                      
                          <Button
                            type="submit"
                          >
                            Update Ticket
                          </Button>                       
    
        </Container>
      );
    }


.....


export async function updateTicket(
    id: string,
    data: TicketFullDTO
): Promise<AxiosResponse<TicketFullDTO>> {
  return await axios.post<TicketFullDTO>(
      `${baseUrl}/management/support/tickets/ticket/${id}`,
      {
        data,
      }
  );
}

export interface TicketFullDTO {
    id?: number,
    title?: string,
    status?: string,
    submitDate?: Moment | null
}

I get error:

MUI: A component is changing the uncontrolled value state of Select to be controlled. Elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled Select element for the lifetime of the component. The nature of the state is determined during the first render. It's considered controlled if the value is not MUI: A component is changing the uncontrolled value state of Select to be controlled. Elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled Select element for the lifetime of the component. The nature of the state is determined during the first render. It's considered controlled if the value is not undefined .

The value for Select should be selected using the value ticket?.status when list ticketStatusList But the data object is not running before rendering the UI content and the value into Select dropdown is not selected.

Do you know how I can fix this issue?

You need to provide a default value to the ticket state, right now you have it as

const [ticket, setTicket] = useState<TicketFullDTO>();

But at the very least, make it a blank TicketFullDTO or null

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM