fix: prevent scroll reset by stabilizing useEffect dependencies with refs
Run Tests / test (push) Failing after 33s

This commit is contained in:
2026-05-16 22:37:11 +02:00
parent b5b5207756
commit 617c8b9d56
2 changed files with 15 additions and 6 deletions
+15 -6
View File
@@ -1,4 +1,4 @@
import { useState, useEffect } from "react"; import { useState, useEffect, useRef, useCallback } from "react";
import { Link } from "react-router"; import { Link } from "react-router";
import Navbar from "../components/Navbar"; import Navbar from "../components/Navbar";
import type { TradingDecision } from "../types/agents"; import type { TradingDecision } from "../types/agents";
@@ -211,10 +211,16 @@ export default function Analyze() {
}, []); }, []);
// Auto-load indicators for stocks that don't have them yet (sequential with delay to avoid rate limits) // Auto-load indicators for stocks that don't have them yet (sequential with delay to avoid rate limits)
const loadingRef = useRef(false);
const stocksRef = useRef(stocks);
stocksRef.current = stocks;
useEffect(() => { useEffect(() => {
const unloaded = stocks.filter((s) => !s.indicatorsLoading && s.indicators.rsi == null); if (loadingRef.current) return;
const unloaded = stocksRef.current.filter((s) => !s.indicatorsLoading && s.indicators.rsi == null);
if (unloaded.length === 0) return; if (unloaded.length === 0) return;
loadingRef.current = true;
let cancelled = false; let cancelled = false;
const loadSequential = async () => { const loadSequential = async () => {
for (const stock of unloaded) { for (const stock of unloaded) {
@@ -227,13 +233,14 @@ export default function Analyze() {
} else { } else {
setStocks((s) => s.map((st) => st.id === stock.id ? { ...st, indicatorsLoading: false } : st)); setStocks((s) => s.map((st) => st.id === stock.id ? { ...st, indicatorsLoading: false } : st));
} }
// 500ms delay between each stock to avoid rate limiting
await new Promise((r) => setTimeout(r, 500)); await new Promise((r) => setTimeout(r, 500));
} }
loadingRef.current = false;
}; };
loadSequential(); loadSequential();
return () => { cancelled = true; }; return () => { cancelled = true; };
}, [stocks]); // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => { useEffect(() => {
const interval = setInterval(() => { const interval = setInterval(() => {
@@ -252,7 +259,8 @@ export default function Analyze() {
}, 60000); }, 60000);
return () => clearInterval(interval); return () => clearInterval(interval);
}, [stocks]); // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const loadIndicators = async (ticker: string) => { const loadIndicators = async (ticker: string) => {
try { try {
@@ -348,7 +356,8 @@ export default function Analyze() {
}; };
updatePositions(); updatePositions();
}, [stocks.length]); // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const removeStock = async (id: string) => { const removeStock = async (id: string) => {
const stock = stocks.find((s) => s.id === id); const stock = stocks.find((s) => s.id === id);
BIN
View File
Binary file not shown.