User stats incorrect in user directory

So this ended up being a nasty “race condition” between the “sentinel” we use to detect when we need to trigger the “load more” action and the rendering of the rows in the users directory :exploding_head:

The Issue

When there were at least 50 users, the /u (users directory) page was triggering loadMore immediately on first load, before the user could scroll down. This caused an unwanted second page of results to load automatically.

Root Cause

Timing race condition during initial page load:

  1. User navigates to /u
  2. controllers/users starts loading data (isLoading: true)
  3. Template renders with ConditionalLoadingSpinner showing spinner
  4. Data arrives, isLoading becomes false
  5. Spinner hides, DirectoryTable begins rendering 50 users
  6. LoadMore sentinel element is inserted into DOM
  7. IntersectionObserver is created and starts watching immediately
  8. At this moment, the table is still calculating layout/expanding to full height
  9. Sentinel is briefly visible in viewport (~292px from top) before table expands
  10. Observer detects intersection → triggers loadMore :cross_mark:
  11. Table finishes expanding to full height (~3689px)
  12. Sentinel moves to correct position (~3959px, below viewport)

The observer was “too eager” - it started watching before the content finished its layout, catching the sentinel during the brief moment when the table hadn’t reached its final height yet.

The Fix

Delay observer creation until content is ready:

Added an @isLoading parameter to LoadMore that prevents the IntersectionObserver from being created when content is still loading.

How It Works Now

Page load → isLoading=true → Modifier skips observer creation
             ↓
Data loads → isLoading=false → Modifier re-runs, creates observer
             ↓
Table fully expanded → Sentinel at correct position (below viewport)
             ↓
User scrolls down → Sentinel enters viewport → loadMore triggers ✓

4 Likes