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

input starts dirty when hydrated #26

Open
jrnxf opened this issue Mar 24, 2024 · 13 comments
Open

input starts dirty when hydrated #26

jrnxf opened this issue Mar 24, 2024 · 13 comments

Comments

@jrnxf
Copy link

jrnxf commented Mar 24, 2024

If I have an atom defined like this

export const nameAtom = atomWithValidate("", {
  validate: (name) => {
    try {
      name.parse(name);
      return name;
    } catch (err: any) {
      throw err.issues;
    }
  },
});

and hydrate it via

useHydrateAtoms([[nameAtom, "hello world"]);

the input will start as dirty, since "hello world" !== "". If an atom is hydrated, what it is hydrated with should be the initial value that is checked against to determine if the input is dirty or not.

@barelyhuman
Copy link
Collaborator

Thanks for the report, i'll get back to you once I have time to check the reasoning

@jrnxf
Copy link
Author

jrnxf commented Mar 24, 2024

You bet! The reason I bring it up is because the current system works great when you start in an empty form, but if you want to start on a form with values already filled out, all the inputs with values with pre-filled data will be dirty, even though you never touched them yourself.

One idea would be to create a new function signatrue allow users to pass in a secondary value that can be used as the value to compare against, instead of just relying on the initial value. Something like this

existing

export const nameAtom = atomWithValidate("", {
  validate: (name) => { ... },
});

proposal

export const nameAtom = atomWithValidate("", "< this string will be used to compare against >", {
  validate: (name) => { ... },
});

@jrnxf
Copy link
Author

jrnxf commented Mar 24, 2024

Before you spend any time on this, I have a POC solution working great locally, I need to head out for the day, but can open a starter PR to get the conversation going!

@daniel-rodrigue
Copy link

If this idea goes ahead, personally I would propose a slightly different api signature:

export const nameAtom = atomWithValidate("", {
  initialValue: "< this string will be used to compare against >",
  validate: (name) => { ... },
});

This new option could help with this idea of passing an atom as the value.

@barelyhuman
Copy link
Collaborator

This should be doable once the react utils exports are done, can be followed here
#27

@barelyhuman
Copy link
Collaborator

If this idea goes ahead, personally I would propose a slightly different api signature:

export const nameAtom = atomWithValidate("", {
  initialValue: "< this string will be used to compare against >",
  validate: (name) => { ... },
});

This new option could help with this idea of passing an atom as the value.

Sorry missed this,

in both API's it seems like you already have access to the value you wish to compare against, why not just pass it to the atom to begin with?

export const nameAtom = atomWithValidate("originalValue", {
  validate: (name) => { ... },
});

useHydrateAtoms was for SSR cases where the atoms are re-created and the original atom might already have been initialised, that isn't always the case with forms so it should be fine to just add in the original value as the first param, unless you are using the nameAtom as both a default store and also wish to add in initial value to the form after a data fetch.

For async atom creation, we don't have anything in this library right now which is why the original request makes sense, though the original jotai library doesn't signal a hydration on the atom which makes it hard for this to work with the original for SSR.

@dai-shi how bad of an idea is it if we export the hydrated store for the library to make use of?

@dai-shi
Copy link
Member

dai-shi commented May 28, 2024

how bad of an idea is it if we export the hydrated store for the library to make use of?

Sorry, I don't follow. Can you elaborate please? Is it about jotai-form, or jotai itself?

@barelyhuman
Copy link
Collaborator

how bad of an idea is it if we export the hydrated store for the library to make use of?

Sorry, I don't follow. Can you elaborate please? Is it about jotai-form, or jotai itself?

Jotai has a map of hydrated atoms that it uses to avoid double hydration on the same atom during SSR, would it be a problem if we exported a getter for that map?

@dai-shi
Copy link
Member

dai-shi commented May 29, 2024

I see. As you may guess, I would like to avoid exposing it.
At the same time, I'm not confident that useHydrateAtoms cover various cases.
Maybe it's time to reconsider the hydration scenario from scratch.
(Though, I still don't follow the discussion. Can it be described without jotai-form context?)

@barelyhuman
Copy link
Collaborator

The discussion is about being able to re-initialize the form atom with a different value over a period of time (which I think is a valid requirement) but, the API's presented by the other developers seem to point in a direction where the value is already known at initialization which doesn't make sense since you could just pass it as the initial value instead

@dai-shi
Copy link
Member

dai-shi commented May 30, 2024

If useHydrateAtoms doesn't work, we generally suggest useEffect.
We've been suggesting so, but we may need to explore a new pattern.
If setAtom in render works without React warning, that might be a (new) solution.

@barelyhuman
Copy link
Collaborator

barelyhuman commented May 30, 2024

in this case the setAtom would create a Dirty form so yep, we need a different helper.

@barelyhuman
Copy link
Collaborator

We could do something like so to allow the RESET, and also add in a wrapper to avoid the awkwardness of using the constants
#31

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

4 participants