I am creating a page for user to update personal data with React-Hook-Form.
Once paged is loaded, I use useEffect
to fetch the user's current personal data and set them into default value of the form.
I put the fetched value into defaultValue
of <Controller />
.
However, it is just not showing in the text box.
Here is my code:
import React, {useState, useEffect, useCallback} from 'react';
import { useForm, Controller } from 'react-hook-form'
import { URL } from '../constants';
const UpdateUserData = props => {
const [userData, setUserData] = useState(null);
const { handleSubmit, control} = useForm({mode: 'onBlur'});
const fetchUserData = useCallback(async account => {
const userData = await fetch(`${URL}/user/${account}`)
.then(res=> res.json());
console.log(userData);
setUserData(userData);
}, []);
useEffect(() => {
const account = localStorage.getItem('account');
fetchUserData(account);
}, [fetchUserData])
const onSubmit = async (data) => {
// TODO
}
return (
<div>
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>User Name:</label>
<Controller
as={<input type='text' />}
control={control}
defaultValue={userData ? userData.name : ''}
name='name'
/>
</div>
<div>
<label>Phone:</label>
<Controller
as={<input type='text' />}
control={control}
defaultValue={userData ? userData.phone : ''}
name='phone'
/>
</div>
<button>Submit</button>
</form>
</div>
);
}
export default UpdateUserData;
The called API is working well and the value is actually set to userData
state.
{
name: "John",
phone: "02-98541566"
...
}
I also tried to setUserData
with mock data in useEffect()
, and it doesn't work either.
Is there any problem in my above code?
The solution is to use the reset() function from the React Hook Form library, if you execute the function without any parameters ( reset() ) the form is reset to its default values, if you pass an object to the function it will set the form with the values from the object (e.g. reset({ firstName: 'Bob' }) ).
You can set an input's default value with defaultValue/defaultChecked (read more from the React doc for Default Values). You can pass defaultValues as an optional argument to useForm() to populate the default values for the entire form, or set values on an individual Controller component via its defaultValue property.
Run useEffect on State Change By default, useEffect runs after every render, but it's also perfect for running some code in response to a state change. You can limit when the effect runs by passing the second argument to useEffect.
useEffect() hook runs the side-effect after initial rendering, and on later renderings only if the name value changes.
@tam answer is halfway through what is needed to make it work with version 6.8.3.
You need to provide the default value but also to useEffect to reset. That particular distinction is required if you have a form that you reload with another entity. I have a complete example in CodeSanbox here.
In a nutshell:
You need to define your defaultValues in the userForm
.
const { register, reset, handleSubmit } = useForm({
defaultValues: useMemo(() => {
return props.user;
}, [props])
});
Then you need to listen to potential change.
useEffect(() => {
reset(props.user);
}, [props.user]);
The example in the Code Sandbox allows swapping between two users and have the form change its values.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With