jotaijs / jotai-tutorial

Interactive Jotai tutorials.
https://tutorial.jotai.org
MIT License
38 stars 22 forks source link

Ideas for lesson structure #20

Closed dai-shi closed 1 year ago

dai-shi commented 1 year ago

(Note that this is just an idea. Feedback is welcome.)

github-actions[bot] commented 1 year ago

Awesome! Thanks for taking the time to open an issue. We will have a look and answer as soon as we can.' first issue

vasucp1207 commented 1 year ago

@dai-shi, can you elaborate more on Lesson 2: Atom creaters are you talking about these.

dai-shi commented 1 year ago

https://jotai.org/docs/advanced-recipes/atom-creators is more advanced use cases of atom creators.

An atom creator means simply a function that returns an atom or a set of atoms. It's just a function and it's not some features that the library provides, but it's an important pattern to make a fairly complex use case.

There are some variations depending on the function parameter and return type. what we often do is to define a base atom and returns a derived atom.

const createFooAtom = () => {
  const baseAtom = atom(0)
  const derivedAtom = atom(
    (get) => get(baseAtom),
    (get, set) => set(baseAtom, (c) => c + 1)
  )
  return derivedAtom
}

Creating action atoms would also be a pattern.

const createCounter = () => {
  const baseAtom = atom(0)
  const readOnlyAtom = atom((get) => get(baseAtom))
  const incAtom = atom(null, (get, set) => set(baseAtom, (c) => c + 1))
  const decAtom = atom(null, (get, set) => set(baseAtom, (c) => c - 1))
  return [readOnlyAtom, incAtom, decAtom]

The next step is to receive an atom as a parameter.

const createCounterActionsFromAtom = (baseAtom) => {
  const incAtom = atom(null, (get, set) => set(baseAtom, (c) => c + 1))
  const decAtom = atom(null, (get, set) => set(baseAtom, (c) => c - 1))
  return [baseAtom, incAtom, decAtom]
const createDoubleAtom = (baseAtom) => {
  const derivedAtom = atom((get) => get(baseAtom) * 2)
  return derivedAtom
}
const attachLogOnWrite = (baseAtom) => {
  const derivedAtom = atom(
    (get) => get(baseAtom),
    (get, set, arg) => {
      set(baseAtom, arg)
      console.log('updated', get(baseAtom))
    }
  )
  return derivedAtom
}

Those are just simple ones. There would be more rich ones.

I haven't thought about how to teach these patterns, but thought it's a good lesson in the tutorial.

vasucp1207 commented 1 year ago

Is there any example related to these, I have a hard time understanding the use-case of these types of atoms.

dai-shi commented 1 year ago

Is there any example related to these, I have a hard time understanding the use-case of these types of atoms.

Hm, seems like I'm failing to explain something. atom creators are just JavaScript functions to return atoms. That pattern is used in almost all jotai/utils functions.

So, the basic idea is this.

// suppose, you would create three atoms.
const fooBaseAtom = atom(0) // internal atom
export const fooAtom = atom((get) => get(fooBaseAtom))
export const fooIncAtom = atom(null, (get, set) => set(fooBaseAtom, (c) => c + 1))

// you would then do the same thing.
const barBaseAtom = atom(0) // internal atom
export const barAtom = atom((get) => get(barBaseAtom))
export const barIncAtom = atom(null, (get, set) => set(barBaseAtom, (c) => c + 1))

// feels repetitive, right?
// we can create a function to avoid repetition.
const createCountIncAtoms = (initialValue) => {
  const baseAtom = atom(initialValue)
  const valueAtom = atom((get) => get(baseAtom))
  const incAtom = atom(null, (get, set) => set(baseAtom, (c) => c + 1))
  return [valueAtom, incAtom]
}
// now using the function, we can define two sets of atoms.
export const [fooAtom, fooIncAtom] = createCountIncAtoms(0)
export const [barAtom, barIncAtom] = createCountIncAtoms(0)