shakacode / re-formality

Form validation tool for reason-react
https://re-formality.now.sh
MIT License
244 stars 35 forks source link

Updating form values from outside the form #44

Closed lukashambsch closed 2 years ago

lukashambsch commented 5 years ago

Hi! Thanks for the great library!

Is there a recommended way to update the form values from outside the form?

For example, I have a form where a couple fields will be re-calculated on the backend when another field changes. I'd like to see the form update when its initialValues change. Similar to Formik's enableReinitialize property.

baransu commented 5 years ago

There is PR for enableReinitialize https://github.com/alexfedoseev/re-formality/pull/33 πŸ˜‰

lukashambsch commented 5 years ago

I saw that, but it didn't sound like it was going to be merged soon. So, I was wondering if there was a way to do it w/o that functionality.

baransu commented 5 years ago

It should be up to date with master so waiting for @alexfedoseev to decide what next πŸ™‚

alex35mil commented 5 years ago

Hey, sorry, I totally missed updates in #33. I looked into it real quick and I have few questions regarding provided use case. In the PR when initial state changes, Reset action is being dispatched, which means the whole validation state is dropped (and AFAICT current input is dropped as well in favor of updated initial input).

So 2 things to discuss:

  1. I'm not sure if it's ok (UX wise) to drop validation state if the goal is to just update some values from outside instead of to reinitialize the whole thing.
  2. If I'm not mistaken, when initial state changed, the whole current input is dropped. Is this intended behavior?
baransu commented 5 years ago

My usecase is the same form for creating and updating. When I mount my component, its asking server for details to display, if non provided nothing happens and user have empty form, if data is returned I replace the current form state with data from server. For me the usecase is the same as incremental key on Form component thats updated after API fulfillment. I’m not sure if its best solution but it works for me.

It would be great to have official guideline how to handle such cases in FAQ section.

alex35mil commented 5 years ago

When I mount my component, its asking server for details to display, if non provided nothing happens and user have empty form, if data is returned I replace the current form state with data from server

@baransu This replace part sounds unsafe to me: what if user is on flaky connection, request hanged for some time and user started typing something in the form. Then request is resolved and all of the sudden current state is replaced w/ resolved data. Also, I would be quite surprised as a user to get an empty edit form.

TBH I incline to mental model where data fetching is not a form's concern, i.e. I would suggest to fetch required data for a form beforehand so when the form is rendered it's 100% ready to use.

baransu commented 5 years ago

I totaly agree. As I said its not best solution but right now it works for me :)

BlueHotDog commented 4 years ago

Hi, coming to this from a similar usecase, i understand the suggested solution is not what @alexfedoseev wants, but. what's the way to actually do that?

alex35mil commented 4 years ago

@BlueHotDog Can you elaborate on details?

BlueHotDog commented 4 years ago

Actually, managed to resolve this by using :

form.updateX((input, _val) => {...input, x: newVal}, newVal);

from within an effect

alex35mil commented 4 years ago

Yeah, with hooks api it’s way easier to trigger such updates. Good thing we changed api to input => input shape to avoid stale input issues. Props to @johnhaley81!

EnriqueVidal commented 4 years ago

I am currently stuck on this, my form is an edit form which means that I need to fetch data from apollo and pass it into the ~initialInput argument of useForm, when the page is sever rendered this works fine since apollo will wait for all queries to be resolved but when client side navigating into the form the form won't update once the page is done fetching.

I figured I would only call useForm afer apollo-client is done however that just makes the following error about the correct order of hooks (which I've been trying to figure out).

I also tried hacking something like this:

/* forced udpate */
form.updateName((_, _) => asyncInput, "");

Which feels super hacky because it's attempting to update the whole input record through the updateName hook, this also doesn't work because it queues many re-renders and thus react throws an exception.

I've also tried sending the initialInput as a prop in an effort to trigger a re-render, but it does not seem to help either.

For someone trying to initialize the form with remote data for edit what is the correct course to take?

EnriqueVidal commented 4 years ago

Got it to work byt rendering the switch to the async data itself rather than the component with props by itself, that said I'd like to know if there's a more elegant way to do this

lessp commented 3 years ago

Hmm, I wonder if I'm hitting a similar issue. I'm currently doing this, and I was expecting (perhaps wrongly) that the form would re-initialise when the initialState changes, but it's not. Is this the intended behaviour? @alexfedoseev

I'm using 3.2.0 here by the way!

Form.useForm(
    ~initialState={
    dynamicFormData: DynamicFormData.createInitialState(formPassedAsProp),
    staticField: "",
    },
);
alex35mil commented 3 years ago

@lessp Sorry, missed your comment. Yeah, initial state change doesn't trigger reinitialization. I elaborated on why in this comment. You can workaround it by deriving a key from an initial state and apply it to form component so when key gets changed, component gets remounted.

lessp commented 3 years ago

@lessp Sorry, missed your comment. Yeah, initial state change doesn't trigger reinitialization. I elaborated on why in this comment. You can workaround it by deriving a key from an initial state and apply it to form component so when key gets changed, component gets remounted.

Hey Alex, yeah, I worked around it, just wanted to make sure. πŸ™‚ Thanks for the reply and keep up the good work!