Awesome Reviewers

When an app is gated by async readiness (hub connected/ready, auth, data bootstrap), prefer keeping the main app mounted and switching visibility to preserve user state—BUT gate side-effects so hide/show doesn’t re-run one-time initialization. Also, when failure occurs, replace (don’t cover) the app UI if any mounted dialogs/popovers could keep focus traps or disable body pointer events.

Apply this pattern:

Example sketch:

function useRemoteEnvironmentBootstrap() {
  const hasBootstrappedRef = useRef(false);

  useEffect(() => {
    if (!initializationSucceeded) return;

    // Always refresh active environment on load/reconnect.
    dispatch({ type: "refresh-active-environment" });

    // Only run initial navigation once.
    if (!hasBootstrappedRef.current) {
      hasBootstrappedRef.current = true;
      dispatch({ type: "select-environment-draft", payload: { draftId } });
    }
  }, [initializationSucceeded, dispatch, draftId]);
}

export function Home({ hubStatus }) {
  const [loaded, setLoaded] = useState(false);
  const hubReady = hubStatus === "ready";
  const hubFailed = hubStatus === "failed";

  useEffect(() => {
    if (hubReady) setLoaded(true);
  }, [hubReady]);

  const showApp = loaded && !hubFailed;

  return (
    <>
      {showApp ? (
        <Activity mode={hubReady ? "visible" : "hidden"}>
          <App />
        </Activity>
      ) : (
        <HubStartupScreen />
      )}
    </>
  );
}

This standard reduces focus/pointer bugs, preserves user context across transient connectivity, and prevents incorrect “re-navigation” on every hide/show cycle.