T
TanStack•3y ago
metropolitan-bronze

input data not populated

So I have a form
const [formData, setFormData] = useState({
age: '',
height: '',
weight: '',
});
const onChange = (event: ChangeEvent<HTMLInputElement>): void =>
setFormData({...formData, [event.target.name]: event.target.value});
const [formData, setFormData] = useState({
age: '',
height: '',
weight: '',
});
const onChange = (event: ChangeEvent<HTMLInputElement>): void =>
setFormData({...formData, [event.target.name]: event.target.value});
For input looks like those:
<Input
label="Age"
name="age"
type="number"
min={1}
max={150}
title="Age is required"
required
value={formData.age}
handleChange={(e): void => onChange(e)}
/>
<Input
label="Age"
name="age"
type="number"
min={1}
max={150}
title="Age is required"
required
value={formData.age}
handleChange={(e): void => onChange(e)}
/>
Those are actually number input, so I want to fetch the data, then change the initial data of those forms.
const {isLoading} = useQuery(['data'],
async()=> {some func },
{
onSuccess: (res)=> {setFormData({
age: res.age,
height: res.height,
weight: res.weight
})
}}
)
const {isLoading} = useQuery(['data'],
async()=> {some func },
{
onSuccess: (res)=> {setFormData({
age: res.age,
height: res.height,
weight: res.weight
})
}}
)
So the STRANGE thing is... I definitely get the res, but they are NOT set into the formData. So I don't see the new values I am getting in the input form. How come?
25 Replies
adverse-sapphire
adverse-sapphire•3y ago
I would try adding console.log(res) inside onSuccess() , do you get the expected data in there?
metropolitan-bronze
metropolitan-bronzeOP•3y ago
@Louis we just looked into something similar a few days ago, and this was what we did and it solved the problem. So I don't get it why I am getting this error now... @julien Yes, I definitely get that res in the console, that's why I know for sure res.age is right number... and for others too.
adverse-sapphire
adverse-sapphire•3y ago
It could also depend on how you're giving the values to the form. For example, if you use defaultValue, only the first value is considered.
metropolitan-bronze
metropolitan-bronzeOP•3y ago
And to make things MORE WEIRD, it happens only to some accounts, and for some accounts it works as expected.... So first we have some default values, then when we get the res, we set the values into the form. But now for some account, it was always initial/default values in the form...
adverse-sapphire
adverse-sapphire•3y ago
Are you able to show the code where formData is given to the number inputs?
metropolitan-bronze
metropolitan-bronzeOP•3y ago
Sure, I will add that part When I sent data, of course they are converted to numbers, and I am getting them as numbers. I just have trouble display them in the input field, so something is wrong in that setFormData...
adverse-sapphire
adverse-sapphire•3y ago
Looks good to me. The only thing I can think of is since you're using a custom <Input> instead of the standard <input>, maybe the value is not properly relayed inside there? To confirm it, if you try switching <Input> with <input> (and rename handeChange to onChange), does it work better? You can also try to add console.log(formData) inside the component, to make sure that formData is updated as expected.
metropolitan-bronze
metropolitan-bronzeOP•3y ago
the Input doesn't have any problem, as I use this for another component with input form, and that one works... So what I can confirm yes, within onSuccess, after I setForm(), then I console.log that formData, I am still getting the initial/default data. That's where it confuses me... In my another component, when I console.log formData after the setForm, it will show up as value already changed....
adverse-sapphire
adverse-sapphire•3y ago
Do you console.log inside onSuccess or inside the body of the component?
metropolitan-bronze
metropolitan-bronzeOP•3y ago
inside the onSuccess block:
{
onSuccess: (res) => {
setFormData({
firstname: res.data.firstname,
lastname: res.data.lastname,
});
console.log('PROFILE', formData);
},
{
onSuccess: (res) => {
setFormData({
firstname: res.data.firstname,
lastname: res.data.lastname,
});
console.log('PROFILE', formData);
},
And it shows up as
PROFILE {firstname: 'John', lastname: 'Doe'}
PROFILE {firstname: 'John', lastname: 'Doe'}
So exactly the same trick, but that age, height, weight component has formData as initial/default value instead... why does it happen like that?!
adverse-sapphire
adverse-sapphire•3y ago
ah yeah, the state is not immediately updated after calling setState, it is updated at the next render. If you move the console.log outside of onSuccess and put it directly inside the body of the component you should see an update (you'll get multiple logs but one of them should be the updated value)
metropolitan-bronze
metropolitan-bronzeOP•3y ago
the weird thing is when we log in with account A it displays, when we log in with account B, it doesn't... so I am out of ways to really debug this so no matter outside or inside onSuccess, that formData was just never changed...
adverse-sapphire
adverse-sapphire•3y ago
hmm, that's odd. Are you able to share the entire component (including the console.log)? Maybe if I see the whole picture I'll be able to spot something.
metropolitan-bronze
metropolitan-bronzeOP•3y ago
I haven't done any other settings in useQuery... and two components are very similar, so I have no idea why one works, the other one doesn't... and when it doesn't, it works on some account, and not on some other.... most weird thing I've seen 😭 I also have another question the other day about auth, I think it happens the same way. Edit: seems I can't link to questions... I will mention you there instead. The auth was never set ... just like the formData here.
adverse-sapphire
adverse-sapphire•3y ago
So the auth issue is a bit more complex since it involves multiple hooks. Here if it's all in the same component, are you able to share the code of the entire component?
sensitive-blue
sensitive-blue•3y ago
Hi 👋 There's not enough context here unfortunately. Please provide a minimal reproducible example if you'd like us to take a proper look at it
metropolitan-bronze
metropolitan-bronzeOP•3y ago
Yeah... maybe that's the best....I will try it out tmr
sensitive-blue
sensitive-blue•3y ago
Sure thing
metropolitan-bronze
metropolitan-bronzeOP•3y ago
Ok, so I experimented with just one field,
const [age, setAge] = useState<string | number>('');
...
then onSuccess, I setAge(res.age);
then my input is like:
<Input
label="Age"
name="age"
type="number"
min={1}
max={150}
title="Age is required"
required
value={age}
handleChange={(e:ChangeEvent<HTMLInputElement>): void => setAge(e.target.value)}
/>
const [age, setAge] = useState<string | number>('');
...
then onSuccess, I setAge(res.age);
then my input is like:
<Input
label="Age"
name="age"
type="number"
min={1}
max={150}
title="Age is required"
required
value={age}
handleChange={(e:ChangeEvent<HTMLInputElement>): void => setAge(e.target.value)}
/>
Now it totally works as expected. So why wouldn't the formData way work? That would be much less code for long forms...
sensitive-blue
sensitive-blue•3y ago
I think a reproduction would be helpful here if you can put one together I'm going to mark this as answered as this is most probably an issue with your implementation that we can't see enough of to help you further. Please feel free to continue the conversation if you can provide any more context and I'll do my best to help :reactquery:
metropolitan-bronze
metropolitan-bronzeOP•3y ago
Should I open a new thread or continue with this one when I have time to isolate this and show a code sandbox?
sensitive-blue
sensitive-blue•3y ago
Please feel free to continue this thread as it has some useful context in 🙂
metropolitan-bronze
metropolitan-bronzeOP•3y ago
I've created a sandbox, copied my sample code there, just the number input for age, and date input. Exactly the same components and code structure I am using.... but there is NO ERROR at all in the reproduction. https://codesandbox.io/s/cranky-khayyam-fjywfp?file=/src/App.js
AnnieTaylorCHEN
CodeSandbox
cranky-khayyam-fjywfp - CodeSandbox
cranky-khayyam-fjywfp by AnnieTaylorCHEN using @tanstack/react-query, @tanstack/react-query-devtools, react, react-dom, react-scripts
metropolitan-bronze
metropolitan-bronzeOP•3y ago
UPDATE: it seems to happen all the time, when I am out of ways to debug then it will come to me and I suddenly solve the issues. So my whole long form issue was caused by me trying to update the formData AGAIN AFTER the setFormData() call. So it was causing some unpleasant race condition I think. So the correct way is to put that validation or changes inside setFormData({ param: validateThisValue? initialValue: newFormDataParamValue }) @julien @Louis Just to let you know I've finally solved this. Thanks a lot for helping! It's indeed hard to debug this but at least I've proved the way I write to work with React Query was correct lol.
sensitive-blue
sensitive-blue•3y ago
Well done! You'll need to use a functional update if you're updating a state value more than once before a re-render if it depends on the previous state value. See: https://blog.louisyoung.co.uk/why-functional-state-updates-are-important/ I'm glad it's sorted :reactquery:

Did you find this page helpful?