これは、ユーザーディレクトリの行のレンダリングと、「さらに読み込む」アクションをトリガーする必要があるかどうかを検出するために使用する「センチネル」との間の、厄介な「競合状態」になりました ![]()
問題点
ユーザーが少なくとも50人いる場合、「/u」(ユーザーディレクトリ)ページは、ユーザーがスクロールする前に、最初の読み込み時にすぐに loadMore をトリガーしていました。これにより、意図しない2ページ目の結果が自動的に読み込まれていました。
原因
初期ページ読み込み中のタイミング競合状態:
- ユーザーが
/uに移動します controllers/usersがデータの読み込みを開始します (isLoading: true)- テンプレートが
ConditionalLoadingSpinnerを表示してレンダリングされます - データが到着し、
isLoadingがfalseになります - スピナーが非表示になり、
DirectoryTableが50人のユーザーのレンダリングを開始します - LoadMore センチネル要素が DOM に挿入されます
- IntersectionObserver が作成され、すぐに監視を開始します
- この時点で、テーブルはまだレイアウトを計算中/完全な高さに展開中です
- テーブルが展開する前の短い時間(上から約292px)でセンチネルが表示されます
- オブザーバーが交差を検出 →
loadMoreをトリガーします
- テーブルが完全な高さ(約3689px)まで展開を完了します
- センチネルが正しい位置(ビューポートの下、約3959px)に移動します
オブザーバーが「性急」すぎました。コンテンツのレイアウトが完了する前に監視を開始し、テーブルが最終的な高さに達する前の短い瞬間にセンチネルを捉えてしまいました。
修正
コンテンツが準備できるまでオブザーバーの作成を遅延させる:
LoadMore に @isLoading パラメータを追加し、コンテンツがまだ読み込み中の場合に IntersectionObserver が作成されないようにしました。
現在の動作
ページ読み込み → isLoading=true → Modifier はオブザーバー作成をスキップします
↓
データ読み込み → isLoading=false → Modifier が再実行され、オブザーバーが作成されます
↓
テーブルが完全に展開 → センチネルが正しい位置(ビューポートの下)にあります
↓
ユーザーが下にスクロール → センチネルがビューポートに入る → loadMore がトリガーされます ✓