Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updateInputsWithValue doesn't trigger onChange? #566

Closed
adsee42 opened this issue Sep 19, 2020 · 9 comments
Closed

updateInputsWithValue doesn't trigger onChange? #566

adsee42 opened this issue Sep 19, 2020 · 9 comments

Comments

@adsee42
Copy link

adsee42 commented Sep 19, 2020

I have a form that saves its content every time 3 seconds after a user typing event, to localStorage.

And if user refreshes page, the content inside localStorage will be loaded and the form is updated with that content by updateInputsWithValue.
Also there is a button that submit the form which is disabled by isChanged === false.

The flow is:

  1. load from localStorage (useEffect)
  2. update form (same useEffect)
  3. when form changed, set state isChanged = true (onChange)

However, it seems that updateInputsWithValue doesn't trigger onChange, so if some changes saved in localStorage, and is loaded, the button is disabled since isChanged does not get updated.

Any suggestions?

@rkuykendall
Copy link
Member

This is very interesting, but I'm having a little trouble following. Where is the isChanged value stored that the input is being disabled by? The form should know that isChanged is true (I think), so it sounds like your version of it isn't being updated because onChange isn't called. But why not just set it when you load localStorage and find data? or store isChanged in localStorage alongside the form data you're saving?

@adsee42
Copy link
Author

adsee42 commented Sep 23, 2020

I chose to set isChanged manually after updateInputsWithValue; and I have to compare the initial values with saved values to determine if the saved values are different and should be loaded. But it worked.
Thanks!

So programmatical changes to the form content would not trigger onChange?
Is it possible to add a prop when initialize formsy to choose the behavior? (onChange triggered or not triggered by programmatical operations)

@rkuykendall
Copy link
Member

Yeah at the moment we don't. It's a bit odd to say "tell me you changed after I change you." You're using it as a round-about way of fetching the isChanged. I think it would be better to just fetch that directly. I think this is just an issue of missing documentation, because it looks like you can call form.isChanged() to get that value. Can you confirm, and I'll add it to the documentation?

@adsee42
Copy link
Author

adsee42 commented Sep 24, 2020

I didn't know that isChanged() is a function of formsy...
I was talking about my component's state const [isChanged, setIsChanged] = useState(false)

And isChanged() did return a boolean value.
But updateInputsWithValue takes some time to update form, so isChanged() returns false if called immediately after updateInputsWithValue. Is there better way than using setTimeout?

tell me you changed after I change you

Isn't that what onChange does? So we can do something when the change is done successfully.

@adsee42
Copy link
Author

adsee42 commented Sep 25, 2020

Fun thing I just realized:
although updateInputsWithValue() would not trigger onChange,
reset() does trigger onChange.

I haven't found the source code so I cannot be very sure, but from my component I did observe this behavior.
Wondering why is that.

@felixmosh
Copy link
Contributor

This is the source-code of updateInputsWithValue

@rkuykendall
Copy link
Member

@felixmosh Thoughts on making updateInputsWithValue trigger an onChange call? I worry about loops a bit, like what if someone calls updateInputsWithValue in their onChange to fix or tweak values. Especially since @adsee42 mostly wants it for the isChanged value, which we should document and make sure works without them having to sleep. That seems like something we could do easily.

@felixmosh
Copy link
Contributor

I don't think that updateInputsWithValue should trigger the onChange prop... because it was set from the "outside".

Maybe it is better to change the isChanged flag on this method?

@adsee42
Copy link
Author

adsee42 commented Jan 28, 2021

After leaving the problem for 4 months, I think now I can figure out how to implement what I want:

The core of the problem is to determine if form's currentValue === form's initialValue

===

What I wanted to do 4 months ago was:

Click to expand!
  1. manage form-changed with state
const [isChanged, setIsChanged]  = useState(false)
  1. on form change (user typing or updateInputsWithValue)
const handleChange = (currentValue, isChanged) => {
  if (!isChanged) return;
  clearTimeout(timer);
  timer = setTimeout(() => {
    save_to_local(currentValue)
    setIsChange(!_.isEqual(currentValue, fetched_remote_profile_data))
  })
}

===

But since updateInputsWithValue doesnot trigger onChange, I have to manage the form data with useState

Click to expand!

on page first render

  1. form rendered with some initial values controlled by useState(initialValues) (user profile, for example)
const [profile, setProfile] = useState(fetched_remote_profile_data)
  1. after component did mount, check local storage for save values
useEffect(() => {
  const saved = read_from_local()
  if (saved) setProfile(saved)
}, [])

the submit button

button is disabled if no changes have been made to the form

<button disabled={_.isEqual(profile, fetched_remote_profile_data)}>submit</button>

on user types

let timer;
...
const handleChange = (currentValue, isChanged) => {
  if (!isChanged) return;
  setProfile(currentValue);
  clearTimeout(timer);
  timer = setTimeout(() => {
    save_to_local(currentValue)
  })
}

===

Or maybe with getModel? (haven't tried this):

<button disabled={_.isEqual(formRef.current.getModel(), fetched_remote_profile_data)}>submit</button>

===

Or a global isPristine as I mentioned in another issue

<button disabled={formRef.current.isPristine}>submit</button>

Anyway, this has little to do with updateInputsWithValue so I'm closing the issue for now.

Thanks for all your supports!!❤️

(Though for me, it feels very intuitive to trigger an onChange any time the value of the form changes...🙃)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants