6.19.6: Кеш-first и отмена запросов при смене доски
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 1m17s

This commit is contained in:
poignatov
2026-03-18 16:24:32 +03:00
parent 6dc3ec828f
commit 01cd0e9003
3 changed files with 46 additions and 22 deletions

View File

@@ -1 +1 @@
6.19.5
6.19.6

View File

@@ -1,6 +1,6 @@
{
"name": "play-life-web",
"version": "6.19.5",
"version": "6.19.6",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -131,9 +131,9 @@ function ShoppingList({ onNavigate, refreshTrigger = 0, isActive = false, initia
const [postponeDate, setPostponeDate] = useState('')
const [isPostponing, setIsPostponing] = useState(false)
const [toast, setToast] = useState(null)
const fetchingRef = useRef(false)
const initialFetchDoneRef = useRef(false)
const prevIsActiveRef = useRef(isActive)
const itemsAbortRef = useRef(null)
// Refs для закрытия диалогов кнопкой "Назад"
const historyPushedForDetailRef = useRef(false)
@@ -185,16 +185,40 @@ function ShoppingList({ onNavigate, refreshTrigger = 0, isActive = false, initia
}
// Загрузка товаров
const fetchItems = async (boardId) => {
if (!boardId || fetchingRef.current) return
fetchingRef.current = true
setLoading(true)
const fetchItems = async (boardId, { background = false } = {}) => {
if (!boardId) return
// Отменяем предыдущий запрос если есть
if (itemsAbortRef.current) {
itemsAbortRef.current.abort()
}
const abortController = new AbortController()
itemsAbortRef.current = abortController
if (!background) {
// Показываем loading только если нет кеша
try {
const cached = localStorage.getItem(`${ITEMS_CACHE_KEY}_${boardId}`)
if (cached) {
setItems(JSON.parse(cached) || [])
setLoading(false)
} else {
setLoading(true)
}
} catch (err) {
setLoading(true)
}
}
setError('')
try {
const res = await authFetch(`/api/shopping/boards/${boardId}/items`)
const res = await authFetch(`/api/shopping/boards/${boardId}/items`, {
signal: abortController.signal
})
if (abortController.signal.aborted) return
if (res.ok) {
const data = await res.json()
if (abortController.signal.aborted) return
setItems(Array.isArray(data) ? data : [])
try {
localStorage.setItem(`${ITEMS_CACHE_KEY}_${boardId}`, JSON.stringify(data))
@@ -203,14 +227,16 @@ function ShoppingList({ onNavigate, refreshTrigger = 0, isActive = false, initia
setError('Ошибка загрузки товаров')
}
} catch (err) {
if (err.name === 'AbortError') return
setError('Ошибка загрузки товаров')
} finally {
setLoading(false)
fetchingRef.current = false
if (!abortController.signal.aborted) {
setLoading(false)
}
}
}
// Загрузка из кэша
// Загрузка досок из кэша
useEffect(() => {
try {
const cached = localStorage.getItem(BOARDS_CACHE_KEY)
@@ -219,15 +245,6 @@ function ShoppingList({ onNavigate, refreshTrigger = 0, isActive = false, initia
if (data.boards) setBoards(data.boards)
}
} catch (err) {}
if (selectedBoardId) {
try {
const cached = localStorage.getItem(`${ITEMS_CACHE_KEY}_${selectedBoardId}`)
if (cached) {
setItems(JSON.parse(cached) || [])
}
} catch (err) {}
}
}, [])
// Начальная загрузка
@@ -245,13 +262,20 @@ function ShoppingList({ onNavigate, refreshTrigger = 0, isActive = false, initia
setItems([])
setLoading(false)
}
// Отменяем запрос при размонтировании или смене доски
return () => {
if (itemsAbortRef.current) {
itemsAbortRef.current.abort()
}
}
}, [selectedBoardId])
// Рефреш при возврате на таб
useEffect(() => {
if (isActive && !prevIsActiveRef.current && initialFetchDoneRef.current) {
fetchBoards(false)
if (selectedBoardId) fetchItems(selectedBoardId)
if (selectedBoardId) fetchItems(selectedBoardId, { background: true })
}
prevIsActiveRef.current = isActive
}, [isActive])
@@ -260,7 +284,7 @@ function ShoppingList({ onNavigate, refreshTrigger = 0, isActive = false, initia
useEffect(() => {
if (refreshTrigger > 0) {
fetchBoards(false)
if (selectedBoardId) fetchItems(selectedBoardId)
if (selectedBoardId) fetchItems(selectedBoardId, { background: true })
}
}, [refreshTrigger])