Skip to content

#443 useSyncEffect Breaks useFind Reactivity Under Suspense #437

@welkinwong

Description

@welkinwong

In the client-side implementation of suspense/useFind, useFindClient is used.
PR #433 introduced useSyncEffect, which sets a 1000ms timeout.

const useSyncEffect = (effect, deps) => {
  const [cleanup, timeoutId] = useMemo(
    () => {
      const cleanup = effect();
      const timeoutId = setTimeout(cleanup, 1000);
                                     ↖︎here
      return [cleanup, timeoutId];
    },
    deps
  );

  useEffect(() => {
    clearTimeout(timeoutId);

    return cleanup;
  }, [cleanup]);
};

When used with Suspense, if code after useFindClient (e.g., the Suspense-compatible useSubscribe) throws a promise and triggers Suspense fallback:

  1. The useEffect inside useSyncEffect is not called (due to rendering being suspended),
  2. But the 1000ms timeout remains active in the background.

Once Suspense resolves the promise and re-renders the component (typically in <1000ms), the timeout fires after re-rendering, triggering its cleanup logic. This prematurely terminates useFind's reactivity

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions