import { useCallback, useEffect, useRef, useState } from 'react' export default function useLazyProfileFavourites({ username, initialFavourites, enabled }) { const hasInitialValue = initialFavourites !== null && initialFavourites !== undefined const initialItems = Array.isArray(initialFavourites) ? initialFavourites : (initialFavourites?.data ?? []) const [items, setItems] = useState(() => initialItems) const [nextCursor, setNextCursor] = useState(() => initialFavourites?.next_cursor ?? null) const [loading, setLoading] = useState(false) const [error, setError] = useState(false) const requestKeyRef = useRef(username) const requestedRef = useRef(hasInitialValue) const abortRef = useRef(null) useEffect(() => { if (requestKeyRef.current === username) return undefined abortRef.current?.abort() abortRef.current = null requestKeyRef.current = username requestedRef.current = false setItems([]) setNextCursor(null) setLoading(false) setError(false) return undefined }, [username]) useEffect(() => { if (requestKeyRef.current !== username || !hasInitialValue) return undefined abortRef.current?.abort() abortRef.current = null requestedRef.current = true setItems(initialItems) setNextCursor(initialFavourites?.next_cursor ?? null) setLoading(false) setError(false) return undefined }, [hasInitialValue, initialFavourites, initialItems, username]) const load = useCallback(async () => { if (!enabled || hasInitialValue || requestedRef.current || !username) return requestedRef.current = true const controller = new AbortController() const requestKey = requestKeyRef.current abortRef.current = controller setLoading(true) setError(false) try { const response = await fetch(`/api/profile/${encodeURIComponent(username)}/favourites`, { headers: { Accept: 'application/json' }, credentials: 'same-origin', signal: controller.signal, }) if (!response.ok) throw new Error('Favourites could not be loaded.') const payload = await response.json() if (requestKey !== requestKeyRef.current || controller.signal.aborted) return setItems(Array.isArray(payload?.data) ? payload.data : []) setNextCursor(payload?.next_cursor ?? null) } catch (caught) { if (caught?.name === 'AbortError' || requestKey !== requestKeyRef.current) return requestedRef.current = false setError(true) } finally { if (requestKey === requestKeyRef.current) { abortRef.current = null setLoading(false) } } }, [enabled, hasInitialValue, username]) useEffect(() => { if (enabled) load() }, [enabled, load]) useEffect(() => () => abortRef.current?.abort(), []) return { items, nextCursor, loading, error, retry: load } }