1

I have a form that updates a record in React. The form first gets details data when edit button is pressed and redirected to the form. The details are then populated in each appropriate form fields for user display.

This is my structure so far:

const EditCrop = () => {
  const dispatch = useDispatch();
  const router = useRouter();
  const cropUuid = router.query.uuid;

  //Defining Component State
  const [cropName, setCropName] = useState('');
  const [cropAbbreviation, setCropAbbreviation] = useState('');
  const [strPartNumber, setStrPartNumber] = useState('');

  // Getting details from redux state to populate them on the form fields 
  const cropDetail = useSelector((state) => state.cropDetail);
  const { loading, error, crop } = cropDetail;

  const cropEdit = useSelector((state) => state.cropEdit);
  const {
    loading: loadingEdit,
    success: successEdit,
    error: errorEdit,
  } = cropEdit;

  useEffect(() => {
    // This to fetch the details once this component loads
    if (!crop || cropUuid) {
      dispatch(getCropDetails(cropUuid));
    } else {
      // This does no set the details form data in the form fields
      setCropName(crop.cropName)
      setCropAbbreviation(crop.cropAbbreviation);
      setStrPartNumber(crop.strPartNumber);
    }
  }, []);

  const cropEditHandler = (e) => {
    e.preventDefault();
    const crop = {
      uuid: cropUuid,
      cropName,
      cropAbbreviation,
      strPartNumber,
    };
    dispatch(editCrop(crop));
  };

return (
    <>
      <Header />
      <Container className="mt--5" fluid>
        <Row>
          <Col className="mb-5 mb-xl-0" xl="8">
            <Card className="bg-secondary shadow">
              <CardHeader className="bg-white border-0">
                <Row className="align-items-center">
                  <Col className="text-left" lg="6">
                    <Link
                      href="/superadminplatform/crops"
                      as="/superadminplatform/crops"
                      className="btn btn-light my-3"
                    >
                      Go Back
                    </Link>
                  </Col>
                  <Col className="text-right" lg="6">
                    <h3 className="mb-0">Edit Crop</h3>
                  </Col>
                </Row>
              </CardHeader>
              <Container>
                <Row>
                  <div className="col text-center">
                    {loading && <Spinner color="success" />}
                  </div>
                </Row>
                <Row>
                  <div className="col text-center">
                    {error && <Alert color="danger" />}
                  </div>
                </Row>
              </Container>

              <CardBody>
                <Container>
                  <Row>
                    <div className="col text-center">
                      {loadingEdit && <Spinner color="success" />}
                    </div>
                  </Row>
                  <Row>
                    <div className="col text-center">
                      {errorEdit && <Alert color="danger" />}
                    </div>
                  </Row>
                </Container>
                <Form onSubmit={cropEditHandler}>
                  {/* { crop.length > 0 && ()} */}
                  <h6 className="heading-small text-muted mb-4">
                    Crop Information
                  </h6>
                  <div className="pl-lg-4">
                    <Row>
                      <Col>
                        <FormGroup>
                          <label
                            className="form-control-label"
                            htmlFor="crop-name"
                          >
                            Crop Name
                          </label>
                          <Input
                            className="form-control-alternative"
                            id="crop-name"
                            placeholder="Enter Crop Name"
                            type="text"
                            value={cropName}
                            onChange={(e) => {
                              setCropName(e.target.value);
                            }}
                          />
                        </FormGroup>
                      </Col>
                    </Row>
                    <Row>
                      <Col>
                        <FormGroup>
                          <label
                            className="form-control-label"
                            htmlFor="crop-abbreviation"
                          >
                            Crop Abbreviation
                          </label>
                          <Input
                            className="form-control-alternative"
                            id="crop-abbreviation"
                            placeholder="Enter Crop Abbreviation"
                            type="text"
                            value={cropAbbreviation}
                            onChange={(e) => {
                              setCropAbbreviation(e.target.value);
                            }}
                          />
                        </FormGroup>
                      </Col>
                    </Row>
                  </div>
                  <hr className="my-4" />
                  {/* Address */}
                  <h6 className="heading-small text-muted mb-4">
                    Palladium Information
                  </h6>
                  <div className="pl-lg-4">
                    <Row>
                      <Col>
                        <FormGroup>
                          <label
                            className="form-control-label"
                            htmlFor="str-part-number"
                          >
                            strPartNumber(Palladium Reference)
                          </label>
                          <Input
                            className="form-control-alternative"
                            id="str-part-number"
                            placeholder="strPartNumber(Palladium Reference)"
                            type="text"
                            value={strPartNumber}
                            onChange={(e) => {
                              setStrPartNumber(e.target.value);
                            }}
                          />
                        </FormGroup>
                      </Col>
                    </Row>
                  </div>
                  <div className="text-right">
                    <Button type="submit" color="primary">
                      Edit Crop
                    </Button>{' '}
                  </div>
                </Form>
              </CardBody>
            </Card>
          </Col>
        </Row>
      </Container>
    </>
  );

How can I be able to populate the details data into the form fields? Since it is not working as intended since am getting this error:

A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.

juliomalves
  • 42,130
  • 20
  • 150
  • 146
  • Where are your inputs? – Camilo Mar 13 '21 at 03:02
  • hey Camilo, there is the updated code with my inputs. Thanks. – Byron Amanphur Mar 13 '21 at 06:22
  • Thanks, it answered as i realized the code in the effect in the else block is not updating the input with fetched details data to map into fields for updating. Where do you think I can put the code to update it since this is nextjs for server and client rendering. – Byron Amanphur Mar 13 '21 at 15:47

0 Answers0