I have a multi-step (2) form that uses Material UI and react-hook-form. On the first step, I ask for a string input (Q1) and an address (Q2). Then, the user clicks next to move onto the second step.
At this point, I use react context to save the data in a global state and pass its values to step 2 on the form but, only the value of Q1 is saved correctly. Q2's value is saved as undefined
.
Simplified code
Step 1 page
//imports here
const StepOne= () => {
const { setValues } = useData();
const methods = useForm({
mode: "all",
shouldUnregister: true
});
const { handleSubmit, control } = methods;
const history = useHistory();
const onSubmit = async (data) => {
setValues({ address: data.address, other: data.other });
history.push("/step2");
};
return (
<MainConatiner>
<Typography variant="h4" component="h2" gutterBottom>
Step one
</Typography>
<FormProvider {...methods}>
<form noValidate onSubmit={handleSubmit(onSubmit)} autoComplete="off">
<AddressInput label="Address" name="address" control={control} />
<Input name="other" label="Other input" control={control} />
<Box mt={2}>
<Button type="submit" size="large" variant="contained">
next
</Button>
</Box>
</form>
</FormProvider>
</MainConatiner>
);
};
Autocomplete compoenent
const AddressInput = ({ control, name, ...rest }) => {
const [value, setValue] = React.useState(null);
const [inputValue, setInputValue] = React.useState("");
const [options, setOptions] = React.useState([]);
const fetch = React.useMemo(
() =>
throttle((request) => {
const getData = getAddress(request?.input);
getData.then((res) => {
setOptions(JSON.parse(res)?.candidates);
return JSON.parse(res).candidates;
});
}, 200),
[]
);
React.useEffect(() => {
let active = true;
if (inputValue === "") {
setOptions(value ? [value] : []);
return undefined;
}
fetch({ input: inputValue }, (results) => {
if (active) {
let newOptions = [];
if (value) {
newOptions = [value];
}
if (results) {
newOptions = [...newOptions, ...results];
}
setOptions(newOptions);
}
});
return () => {
active = false;
};
}, [value, inputValue, fetch]);
return (
<Controller
name={name}
control={control}
render={({ field }) => (
<Autocomplete
{...field}
id="address"
getOptionLabel={(option) =>
typeof option === "string" ? option : option.address
}
filterOptions={(x) => x}
options={options}
autoComplete
includeInputInList
filterSelectedOptions
value={value}
onChange={(event, newValue) => {
console.log(newValue);
setOptions(newValue ? [newValue, ...options] : options);
setValue(newValue);
}}
onInputChange={(event, newInputValue) => {
setInputValue(newInputValue);
}}
renderInput={(params) => (
<TextField {...rest} {...params} variant="outlined" fullWidth />
)}
renderOption={(option) => <span>{option.address}</span>}
/>
)}
/>
);
};
You can find the full code here: https://codesandbox.io/s/multi-step-form-4cgj9?file=/src/pages/Home.js:363-1313
Any ideas?