#What's the recommended way to patch the entire form?

1 messages Β· Page 1 of 1 (latest)

chrome scarab
#

For example, if I'm using the same component to create/edit an entity, I want to replace the default values when there is data in the server for that entity.

How can I push the server data into the form?

Thanks.

sterile musk
#

So are you using the useForm hook? If so you could have a server component where you would fetch and see if there are values and in your client component you could take those values as prop and set it up in default values

chrome scarab
#

I'm using plain React. Not NextJS, unfortunately, but that's a good idea.

sterile musk
#

@steady roost would this be the correct approach?

chrome scarab
#

That's one way. It did cause some issues when I was moving the form field into a child component but it is one way. I was wondering if it was a way to patch the entire form instead of having to enter field by field.

sterile musk
#

yes, you could also change the entire form like this ``` const { state: stateDemo, store } = useForm({
defaultValues: {
name: "first value",
another: "another value",
},
});

useEffect(() => {
console.log("stateDemo", stateDemo);
store.setState((state) => {
return {
...state,
values: {
name: "hello world",
another: "another demo value",
},
};
});
}, []) ```

chrome scarab
#

I will try this

#

Thanks

steady roost
#

As in, it won't be likely to break in future releases for some time

chrome scarab
#

@steady roost this doesn't seems to work for me. The form get the value, but the field does not reflect it. The same happened to me with the setFieldValue.

It does happen that my field is in a child componet if that may be important.

steady roost
#

Huh. Let's open a bug and I'll investigate

#

Minimal repro plz πŸ™‚

chrome scarab
#

I will!

#

Thanks

#

Do you prefer codesandbox or stackblitz?

steady roost
#

I have a minor preference towards StackBlitz, but either way πŸ™‚

chrome scarab
#

Got it!

chrome scarab
#

Uhm the problem is when the form is inside a conditional rendering like an if.

#

I will create the issue soon.

floral trout
#

The field's value set in the useEffect hook appears and suddenly disappears if we force the input element to rerender when field.state.value changes. Interesting

floral trout
#

Ok, I think I made it work:

πŸ”— https://stackblitz.com/edit/stackblitz-starters-gdmagd?file=src%2FApp.tsx

I simply replaced the useEffect hook in your example with these lines:

  const fetchData = useCallback(async () => {
    const p1 = new Promise<{ firstName: string }>((res) =>
      setTimeout(() => res({ firstName: 'Isabelle' }), 3000)
    );
    const data = await p1;

    form.setFieldValue('firstName', data.firstName);
  }, [form]);

  useEffect(() => {
    fetchData();
  }, [fetchData]);

Wdyt?

#

this kinda suggests to me that the issue is changing the state, maybe because that forces us to re-render the component, in which we run the (field) => <input .../> function

#

this is just intuition at this point

floral trout
#

Let's test this hypothesis by profiling the two versions (modifying the state during data fetching vs not modifying):

1. Not modifying the state of <App /> during data fetching (first image)

1 rerender. Field changes bc one of its hooks. This must be because we changed its value when we called form.setFieldValue('firstName', data.firstName).

2. Modifying the state of <App /> during data fetching (second image)

3 commits.
*Commit 1: * (2nd image): The Field rerenders, bc one of its hooks has changed, I think this is when we update it through the api. I think this is the point when see the value we set in the Field.

Commit 2: (3rd and 4th image) <App /> rerenders, bc one of its hooks have changed. I think this is the setXData hook. This causes <Field/> to rerender too (4th image). This must be the point when our value disappears from the field and it starts with a blank state again.

Commit 3: (5th image) Nothing important happens. We can ignore it.

#

maybe if we change the default values of the form, it'll not instantiate the <Field /> with an empty value when it rerenders on the state change.

#

Yes, indeed. This is so much fun 🀣

  const [xData, setxData] = useState(null);

  const form = useForm<{ firstName: string }>({
    defaultValues: {
      firstName: xData?.firstName,
    },
    onSubmit: async ({ value }) => {
      console.log(value);
    },
  });
floral trout
#

Well, I'm not familiar with the Form internals and have a PR in tanstack.com to finish, so I can't continue with this now, but maybe the info I found helps someone else to pick this up

steady roost
floral trout