I'm working on a React application with Typescript. I created a multi-step form. Each form page is it's own component, and fields are separate components. I'm able to view data from Text Fields onSubmit, however, I can't figure out how to do the same with the Select field as that component has its own onChange attribute.
These are snippets from the Main Form. Fields have been changed. Let's pretend "State" is a dropdown:
type FormData = {
firstName: string;
lastName: string;
state: string;
};
const INITIAL_DATA: FormData = {
firstName: "",
lastName: "",
state: "",
};
Hook to get User Data
const [data, setData] = useState(INITIAL_DATA);
function updateFields(fields: Partial<FormData>) {
setData((prev) => {
return { ...prev, ...fields };
});
}
This is how I'm getting all of the steps. NOTE: I cleaned up irrelevant code. This focuses on just the parts that get data:
function getStepsContent(step: number) {
switch (step) {
case 0:
return (
<Personal
{...data}
updateFields={updateFields}
/>
);
case 1:
return (
<Address
{...data}
updateFields={updateFields}
/>
);
default:
return (
<Personal
{...data}
updateFields={updateFields}
/>
);
}
}
On the Personal Form Page, I have:
type PersonalData = {
firstName: string;
lastName: string;
state: string;
}
type PersonalProps = PersonalData & {
updateFields: (fields: Partial<PersonalData>) => void
}
This is an example of the form field. Note: This is where I'm pulling in a custom field components. StyledTextField (uses MUI textfield) pulls in data, the StyledSelectField (uses MUI select field) does not:
<StyledTextField
label="First Name"
name="firstName"
value={firstName}
onChange={e => updateFields({firstName: e.target.value})}
/>
<StyledSelect
label="State"
placeholder="Select One"
name="state"
data={state}
onChange={e => updateFields({state: e.target.value})}
/>
This is my Select Component. It does grab the data, but it doesn't push it through to the form when submitted:
interface IData {
id: number;
name: string;
}
interface StyledSelectProps {
id: string;
label: string;
placeholder: string;
name: string;
onChange?: (event: SelectChangeEvent) => void;
data: IData[];
}
export default function StyledSelect({
id,
label,
placeholder,
name,
onChange,
data,
}: StyledSelectProps) {
const [value, setValue] = useState("");
const handleChange = (event: SelectChangeEvent) => {
setValue(event.target.value);
console.log(event.target.value);
};
return (
<div>
<FormControl fullWidth>
<InputLabel htmlFor={id}>
{label}
</InputLabel>
<Select
id={id}
value={value}
label={id}
name={name}
variant="standard"
defaultValue=""
renderValue={value !== "" ? undefined : () => placeholder}
onChange={handleChange}
>
{data.map(({ id, name }) => (
<MenuItem key={id} value={name}>
{name}
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
I think the main issue is that I have an onChange on the Select, but also need to do an onChange on the single Form Page. Also, because I have values coming through here via useState, I'm not able to call it in on the single Form Page.
Any help and guidance will be greatly appreciated.
CodePudding user response:
On your StyledSelect you should call the onChange from props to get you fn updateFields
called. Update the handleChange fn in StyledSelect component with the following:
const handleChange = (event: SelectChangeEvent) => {
setValue(event.target.value);
onChange(event)
};