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

README poorly explains this package #64

Open
yairEO opened this issue Nov 11, 2024 · 7 comments
Open

README poorly explains this package #64

yairEO opened this issue Nov 11, 2024 · 7 comments

Comments

@yairEO
Copy link

yairEO commented Nov 11, 2024

Hi, I am a veteran javascript developer (also a React developer for many years) and open-source author and I simply cannot understand what this package is for.. The README is written in such a bizarre way, where terminology is used without any explanation.

There is not paragraph about why jotai-scope needed, no real-world minimal examples where one could benefit from this package. basically no introduction.

The below is from the top of the README file, which raises some questions:

Scoped Atom resolution rules

  1. Each ScopeProvider creates a new scope pool.

What is this made-up term "scope pool"? please explain it to me first before using it

  1. If a primitive atom is scoped, its scoped copy will be stored within the scope pool.

What do you mean "scoped copy"? what does this sentence even mean.. why would it be a copy, what is a copy, what is going on here..

  1. If a derived atom is scoped, itself and all of its dependencies will be stored within the scope pool.

What does it mean they are "stored" in the "scope pool". what does "stored" means. again, lacking terminology explanation here. what forbids an atom from being exported and used anywhere... unclear.

  1. If a derived atom is not scoped, but its dependency is scoped, it will access its scoped dependency.
  1. In each scope pool, each atom has at most one scoped copy, so the same scoped atom is shared in the pool.

I have no idea what I have just read

  1. If a derived atom is nested scoped, itself and all of its dependencies will be stored within the scope pool where the atom is marked as scoped.

What does "nested scoped" even means...


Overall I think there is a lot of missing documentation to explain things, as simple as possible, and an ordered way, so first the README should explain the basic necessity for this package, then lay out the terminology and explain the core principles and only then actually use them in sentences.

@dmaskasky
Copy link
Member

dmaskasky commented Nov 11, 2024

Lol, you bring up all fair points. I'll overhaul the documentation so that it will make better sense.

So I can unblock you, feel free to ask me any questions in this thread. These questions will also help me focus on those areas.

Here's a rough first draft:

In Jotai v2, a reactive value is represented by a store + and atom. Both are required to read and write values. If you swap one, then you are dealing with a different reactive value. A reactive value is a value you can read and write to and subscribe to changes.

const a = atom(0)
const store = createStore()

const value = store.get(a)
store.sub(a, () => {
  console.log('a changed')
})
store.write(a, 1)

Using Provider in React, every atom within that context will have its own store, so a different reactive value.

In cases where you need to only have some atoms use a different reactive value in a React subtree, ScopeProvider from jotai-scope can be used.

In the example below, the Form components will use separate stores and the theme atom will be shared.

function Form() {
  const [form, setForm] = useAtom(formAtom)
  const theme = useAtomValue(themeAtom)
}

...
<>
  <Form />
  <ScopeProvider atoms={[formAtom]}>
    <Form />
  </ScopeProvider>
  <ScopeProvider atoms={[formAtom]}>
    <Form />
  </ScopeProvider>
</>

@yairEO
Copy link
Author

yairEO commented Nov 11, 2024

I also am unfamiliar with the term "reactive value" to be honest.

I don't understand why did you say:

Both are required to read and write values

why? First time I read about createStore... it's not mentioned in Jotai's website and I am certainly not using any such store in my app which is full of jotai atoms of all sorts.

I am starting to think the name of this package is misleading. It's not a real scoping, where an atom can only be used within a certain react-subtree and never outside, but in fact, it's only cloning that atom, which can by itself lead to misunderstanding by other developer why an atom is used but its value is not changed. because it isn't the same atom.

All developers within a team will have to have a mindset of "an atom might be a clone and not what I think it is" and start an inquiry where does that clone first originated.

I think this can lead to bugs or time wasted in debugging.

A true scoping is needed. no clones. just atoms which are confined for a specific area and are completely unusable/inaccessible anywhere else even if directly imported.

@dmaskasky
Copy link
Member

You can find documentation on createStore here: https://jotai.org/docs/core/store#createstore

The ScopeProvider scopes the reactive value, not the atom.

I also think there is a mistake in the example code within the official Jotai website:
https://jotai.org/docs/extensions/scope

What is the issue?

@yairEO
Copy link
Author

yairEO commented Nov 11, 2024

Actually after examination (the example) I don't think there is a mistake, but only a misunderstanding by me. It was very difficult to wrap my head around that example.

I couldn't understand why both ScopeProvider has the same atoms prop.
there is no explanation as to what's going on here and the reader is left to guess many things.

After many deep thinking I had come to the conclusion <ScopeProvider atoms={[anotherCountAtom]}> is used twice to showcase the exact same piece of code results in two isolated areas where one area of the code does not affect the other, even though both are apparently using the same atom (anotherCountAtom)

Basically means anotherCountAtom is duplicated within ScopeProvider

<ScopeProvider atoms={[anotherCountAtom]}>
  <Counter />
</ScopeProvider>
<h1>Second Provider</h1>
<ScopeProvider atoms={[anotherCountAtom]}>
  <Counter />
</ScopeProvider>

@dmaskasky
Copy link
Member

In the current implementation of ScopeProvider, anotherCountAtom is duplicated internally.

But in the near future, ScopeProvider will make use of the new store.unstable_derive api to route access to the correct atomState based on the given atom.

Correction: I made a correction to the example I gave earlier. Please have a second look at that example.

@yairEO
Copy link
Author

yairEO commented Nov 11, 2024

In the example below, the Form components will use separate stores and the theme atom will be shared.

Hi, I don't see any store used in your edited example... only formAtom & themeAtom atoms are used, as-is.

function Form() {
  const [form, setForm] = useAtom(formAtom)
  const theme = useAtomValue(themeAtom)
}

...
<>
  <Form />
  <ScopeProvider atoms={[formAtom]}>
    <Form />
  </ScopeProvider>
  <ScopeProvider atoms={[formAtom]}>
    <Form />
  </ScopeProvider>
</>

I also still do not understand why would I ever need a Store. The docs do not provide any hint for which use case a store is helpful or a must (for example, in a React app)

@dmaskasky
Copy link
Member

dmaskasky commented Nov 11, 2024

The ScopeProvider internally creates a store. The store is read by the useAtom and useAtomValue hooks.

You can work with a jotai store manually, but for this example, you don't need to.

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

2 participants