jotaijs / jotai-scope

MIT License
55 stars 4 forks source link

Scope caused `atomWithObservable` to be out of sync #36

Open tien opened 3 months ago

tien commented 3 months ago

Example

The 2 counters below while using the same atom are completely different

const counterSubject = interval(1000).pipe(map((i) => `#${i}`));
const counterAtom = atomWithObservable(() => counterSubject);

const Counter = () => {
  const [counter] = useAtom(counterAtom);
  return <div>count: {counter}</div>;
};

export default function App() {
  return (
    <div className="App">
      <h1>Jotai scope bug</h1>
      <Counter />
      <ScopeProvider atoms={[]}>
        <Suspense>
          <Counter />
        </Suspense>
      </ScopeProvider>
    </div>
  );
}

Reproduction

Code sandbox link

dmaskasky commented 3 months ago

Related: #25

There is currently no way to distinguish between a derived atom that references a scoped atom, and a derived atom that does not. jotai-scope has to copy every derived atom to intercept their getter and setter to address this. As you discovered, this copy can cause problems.

PR #35 adds an api to not copy specified derived atoms. I would merge this but I think there's a better way.

PR #2609 makes a change to the store api that removes the need to copy derived atoms at all. 2609 should merge in a few weeks.

Once 2609 lands I'll rewrite jotai-scope to address the issue you found and #25.

dmaskasky commented 2 months ago

Update: Integrating with https://github.com/pmndrs/jotai/pull/2609 is a lot harder than I imagined. I need to spend more time to understand how to rewrite jotai-scope following these changes.

Also, it looks like an atomWithObservable refactor is in the works with https://github.com/pmndrs/jotai/pull/2631, but unfortunately it looks as though the issue is still present.

https://codesandbox.io/p/sandbox/atom-with-observable-infinite-mount-bug-fix-forked-253y84?file=%2Fsrc%2FApp.tsx%3A6%2C1-7%2C1