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.