atlassian / react-sweet-state

Shared state management solution for React
https://atlassian.github.io/react-sweet-state/
MIT License
871 stars 55 forks source link

Unstable scheduling behavior #217

Open theKashey opened 1 year ago

theKashey commented 1 year ago

I've discovered a few problems with the current implementation mostly related to batch behavior.

Problem 1 - there is a bug

The problem is with boolean variables being not in the right place affecting the way batch works and behavior will change after the first call

Let me indicate the problem

export function batch(fn) {
  // if we are in node/tests or nested schedule
- not in the "nested schedule", but after the first batch call as well
  if (
    !defaults.batchUpdates ||
    !supports.scheduling() ||
    isInsideBatchedSchedule
  ) {
    return unstable_batchedUpdates(fn);
  }

-  isInsideBatchedSchedule = true;
  // Use ImmediatePriority as it has -1ms timeout
  // https://github.com/facebook/react/blob/main/packages/scheduler/src/forks/Scheduler.js#L65
  return scheduleCallback(ImmediatePriority, function scheduleBatchedUpdates() {
    isInsideBatchedSchedule++;
    unstable_batchedUpdates(fn);
    isInsideBatchedSchedule--;
  });
}

Problem 2 - you are done, but we are not

There is a problem with information being stored in multiple places - after "update" many pieces are already seeing the correct information, but sweet-state might be a little late to the party.

The current workaround is to use batch to schedule next event

useEffect(() => {
- doSomething();
+ batch(doSomething);

or even emulate useDeferred

const state = useSweetState(realState);

const useSweetState = (state) => {
  const [value, setValue] = useState(state);
  useEffect(() => {
    // "sync" with sweet state event propagation
    batch(() => setValue(state));
  }, [state]); 
}