fix(web): t-Falle in acht Ladeeffekten entschaerft, RssFeedListForm/SavedSearchBar-Ladefunktionen stabilisiert
Befunde 7-15 der Biome-Regel useExhaustiveDependencies (quick-260921-gof): - VehicleTable, TenderDetail, DigestIntervalForm, SourceConfigForm, favorites-widget: Ersatz-Fehlertext aus useTranslations wird jetzt vor dem Effekt/Rueckruf in eine Konstante gezogen und diese Konstante in die Abhaengigkeitsliste aufgenommen - `t` selbst kommt nirgends mehr in eine Liste. In diesem Projekt ist belegt, dass `t` bei jedem Durchlauf eine frische Funktion ist (Testattrappen), eine `t`- Abhaengigkeit haette den jeweiligen Mount-Abruf zur Schleife gemacht. - RssFeedListForm.tsx und SavedSearchBar.tsx: die Ladefunktionen waren gewoehnliche Funktionen im Rumpf (bei jedem Durchlauf neu) - jetzt in einen stabilen Rueckruf mit der Text-Konstante als einziger Abhaengigkeit eingepackt. - ResultsList.tsx: Befund 8 (t) wie oben, Befund 15 (refreshKey) in den Effekt verschoben, der `load` aufruft, statt in `load` selbst zu stehen - eine begruendete `biome-ignore`-Zeile (erste im Projekt) haelt fest, dass der Auffrisch-Ausloeser der Elternseite ohne diese Abhaengigkeit wirkungslos waere. - Sieben Testdateien um eine Zaehlprobe erweitert: erneutes Zeichnen mit unveraenderten Props darf keinen weiteren Abruf ausloesen; ResultsList zusaetzlich um eine Probe, dass ein refreshKey-Bump genau einen weiteren Abruf ausloest. - DigestIntervalForm hat keine Testdatei - nur am laufenden System auf Meine Quellen geprueft (siehe SUMMARY). - Wirkungslose eslint-disable-Zeilen fuer diese Regel entfallen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TPPB4ApQxzSU1rwV2Ffj9J
This commit is contained in:
@@ -293,4 +293,19 @@ describe('VehicleTable', () => {
|
||||
expect(screen.getByText('errors.loadVehiclesFailed')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('quick-260921-gof (Befund 7): erneutes Zeichnen ohne Prop-Aenderung loest KEINEN weiteren Abruf aus — die Uebersetzungs-Attrappe liefert bei jedem Durchlauf eine frische Funktion, eine Rueckkehr von `t` in die Abhaengigkeitsliste faellt hier sofort auf', async () => {
|
||||
mockFetchVehicles.mockResolvedValue([]);
|
||||
|
||||
const { VehicleTable } = await import(
|
||||
'@/app/(portal)/modules/dkv-fleet/settings/components/VehicleTable'
|
||||
);
|
||||
const { rerender } = render(<VehicleTable />);
|
||||
|
||||
await waitFor(() => expect(mockFetchVehicles).toHaveBeenCalledTimes(1));
|
||||
|
||||
rerender(<VehicleTable />);
|
||||
|
||||
await waitFor(() => expect(mockFetchVehicles).toHaveBeenCalledTimes(1));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -179,18 +179,24 @@ export function VehicleTable() {
|
||||
toastTimerRef.current = setTimeout(() => setToast(null), 4000);
|
||||
}, []);
|
||||
|
||||
// Befund 7 (quick-260921-gof): `t` selbst kommt nicht in die Liste — die
|
||||
// Uebersetzungs-Attrappe in den Tests liefert bei jedem Durchlauf eine
|
||||
// frische Funktion, das wuerde `load` neu erzeugen und den Mount-Effekt
|
||||
// unten (useEffect(() => load(), [load])) zu einer Abruf-Schleife machen.
|
||||
// Stattdessen wird der Text vorgezogen: als Zeichenkette vergleicht React
|
||||
// per Wert, die Liste bleibt ueber Durchlaeufe hinweg gleich.
|
||||
const loadErrorText = t('errors.loadVehiclesFailed');
|
||||
|
||||
const load = useCallback(async () => {
|
||||
try {
|
||||
const data = await fetchVehicles();
|
||||
setVehicles(data);
|
||||
} catch {
|
||||
setTableError(t('errors.loadVehiclesFailed'));
|
||||
setTableError(loadErrorText);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, []); // `t` intentionally excluded: `load` is a dependency of the
|
||||
// mount-time useEffect below, and an unstable `t` identity would turn
|
||||
// that into a fetch-on-every-render loop instead of fetch-once-on-mount.
|
||||
}, [loadErrorText]);
|
||||
|
||||
useEffect(() => {
|
||||
load();
|
||||
|
||||
Reference in New Issue
Block a user