Skip to content

Use functional setState in useCallback for stable callbacks in onboarding tour and sidebar #1005

@MODSetter

Description

@MODSetter

Description

Several useCallback hooks close over state variables to compute the next state, which forces the callback to be recreated every time that state changes. Using the functional form setState(prev => ...) removes the state from the dependency array, producing a stable callback reference.

Vercel React Best Practices Rule: rerender-functional-setstate (5.9)

Files to change

  • surfsense_web/components/onboarding-tour.tsx
  • surfsense_web/components/layout/hooks/useSidebarState.ts

What to do

In onboarding-tour.tsx (lines 676-695):

Change handleNext:

const handleNext = useCallback(() => {
  setStepIndex(prev => {
    if (prev < TOUR_STEPS.length - 1) {
      retryCountRef.current = 0;
      return prev + 1;
    }
    // Tour completed
    if (user?.id) {
      localStorage.setItem(`surfsense-tour-${user.id}`, "true");
    }
    setIsActive(false);
    return prev;
  });
}, [user?.id]);

Change handlePrev:

const handlePrev = useCallback(() => {
  setStepIndex(prev => {
    if (prev > 0) {
      retryCountRef.current = 0;
      return prev - 1;
    }
    return prev;
  });
}, []);

In useSidebarState.ts (lines 39-41):

Change toggleCollapsed:

const toggleCollapsed = useCallback(() => {
  setIsCollapsedState(prev => {
    const next = !prev;
    try {
      document.cookie = `${SIDEBAR_COOKIE_NAME}=${next}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
    } catch {}
    return next;
  });
}, []);

Acceptance criteria

  • handleNext dep array is [user?.id] (not [stepIndex, user?.id])
  • handlePrev dep array is [] (not [stepIndex])
  • toggleCollapsed dep array is [] (not [isCollapsed, setIsCollapsed])
  • Onboarding next/prev still works; sidebar toggle + keyboard shortcut (Cmd+) still works

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions