jotaijs / jotai-scope

MIT License
55 stars 4 forks source link

[WIP] Refactor to use the new jotai store derive method #46

Open dmaskasky opened 1 month ago

dmaskasky commented 1 month ago

Summary of changes

Update ScopeProvider to use the new unstable_derive api on store (https://github.com/pmndrs/jotai/pull/2652). The new code is much simpler and should address https://github.com/jotaijs/jotai-scope/issues/25 and https://github.com/jotaijs/jotai-scope/issues/36.

Changes

  1. Scoped and derived atoms are no longer copied and their init functions are not re-executed. Resolves #25 and #36.
  2. A new optional store prop added to ScopeProvider props. The scoped store will use the internals of this store if provided.
  3. No longer need to monkey patch scoped writable atoms.
  4. Code cleanup. Reduces bundle size.

Tests Results

01_basic_spec

✅ 01. ScopeProvider does not provide isolation for unscoped primitive atoms

base
S0[]: base0
S1[]: base0

✅ 02. unscoped derived atoms are unaffected in ScopeProvider

base, Derived(base)
S0[]: base0 Derived0(base0)
S1[]: base0 Derived0(base0)

✅ 03. ScopeProvider provides isolation for scoped primitive atoms

base
S0[base]: base0
S1[base]: base1

❌ 04. unscoped derived can read and write to scoped primitive atoms

base, derived(base)
S0[base]: derived0(base0)
S1[base]: derived0(base1)

❌ 05. unscoped derived can read both scoped and unscoped atoms

base, notScoped, derived(base + notScoped)
S0[base]: derived0(base0 + notScoped0)
S1[base]: derived0(base1 + notScoped0)

❌ 06. dependencies of scoped derived are implicitly scoped

base, derived(base),
S0[derived]: derived0(base0)
S1[derived]: derived1(base1)

❌ 07. scoped derived atoms can share implicitly scoped dependencies

base, derivedA(base), derivemB(base)
S0[derivedA, derivedB]: derivedA0(base0), derivedB0(base0)
S1[derivedA, derivedB]: derivedA1(base1), derivedB1(base1)

✅ 08. nested scopes provide isolation for primitive atoms at every level

base, derivedA(base), derivedB(base)
S0[base]: base0
S1[base]: base1
S2[base]: base2
S3[base]: base3

❌ 09. unscoped derived atoms in nested scoped can read and write to scoped primitive atoms at every level

baseA, baseB, baseC, derived(baseA + baseB + baseC),
S0[     ]: derived(baseA0 + baseB0 + baseC0)
S1[baseB]: derived(baseA0 + baseB1 + baseC0)
S2[baseC]: derived(baseA0 + baseB1 + baseC2)

❌ 10. inherited scoped derived atoms can read and write to scoped primitive atoms at every nested level

baseA, baseB, derived(baseA + baseB)
S1[baseB, derived]: derived1(baseA1 + baseB1)
S2[baseB]: derived1(baseA1 + baseB2)

02_removeScope

✅ atom get correct value when ScopeProvider is added/removed

03_nested

✅ nested primitive atoms are correctly scoped

baseA, baseB, baseC
S1[baseA]: baseA1 baseB0 baseC0
S2[baseB]: baseA1 baseB2 baseC0

04_derived

❌ parent scope's derived atom is prior to nested scope's scoped base

base, derivedA(base), derivedB(base)
case1[base]: base1, derivedA0(base1), derivedB0(base1)
case2[derivedA, derivedB]: base0, derivedA1(base1), derivedB1(base1)
layer1[derivedA]: base0, derivedA1(base1), derivedB0(base0)
layer2[base, derivedB]: base2, derivedA1(base2), derivedB2(base2)

05_derived_self

❌ derived dep scope is preserved in self reference

baseA, derivedB(baseA, derivedB)
S1[baseA]: baseA1, derivedB0(baseA1, derivedB0)

06_implicit_parent

✅ level 1: "BD" and level 2: "BD" ✅ level 1: "BD" and level 2: "DB" ✅ level 1: "DB" and level 2: "BD" ✅ level 1: "DB" and level 2: "DB"

07_writable

✅ "writableAtom" updates its value in both scoped and unscoped and read scoped atom (27 ms) ✅ "thisWritableAtom" updates its value in both scoped and unscoped and read scoped atom (5 ms)

writable=w(,w + s), base=b
S0[ ]: b0, w0(,w0 + b0)
S1[b]: b1, w0(,w0 + b1)