6.15.1: Фикс race condition при смене доски желаний
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m25s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m25s
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "play-life-web",
|
||||
"version": "6.15.0",
|
||||
"version": "6.15.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -51,9 +51,11 @@ function Wishlist({ onNavigate, refreshTrigger = 0, isActive = false, initialBoa
|
||||
const fetchingCompletedRef = useRef(false)
|
||||
const initialFetchDoneRef = useRef(false)
|
||||
const prevIsActiveRef = useRef(isActive)
|
||||
const selectedBoardIdRef = useRef(getInitialBoardId())
|
||||
|
||||
// Обёртка для setSelectedBoardId с сохранением в localStorage
|
||||
const setSelectedBoardId = (boardId) => {
|
||||
selectedBoardIdRef.current = boardId
|
||||
setSelectedBoardIdState(boardId)
|
||||
try {
|
||||
if (boardId) {
|
||||
@@ -171,69 +173,83 @@ function Wishlist({ onNavigate, refreshTrigger = 0, isActive = false, initialBoa
|
||||
}
|
||||
|
||||
// Загрузка желаний выбранной доски
|
||||
const fetchItems = async () => {
|
||||
if (!selectedBoardId || fetchingRef.current) return
|
||||
const fetchItems = async (boardId) => {
|
||||
if (!boardId || fetchingRef.current) return
|
||||
fetchingRef.current = true
|
||||
|
||||
|
||||
try {
|
||||
const hasDataInState = items.length > 0 || completedCount > 0
|
||||
if (!hasDataInState) {
|
||||
const cacheLoaded = loadItemsFromCache(selectedBoardId)
|
||||
const cacheLoaded = loadItemsFromCache(boardId)
|
||||
if (!cacheLoaded) {
|
||||
setLoading(true)
|
||||
}
|
||||
}
|
||||
|
||||
const response = await authFetch(`${API_URL}/boards/${selectedBoardId}/items`)
|
||||
|
||||
|
||||
const response = await authFetch(`${API_URL}/boards/${boardId}/items`)
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Ошибка при загрузке желаний')
|
||||
}
|
||||
|
||||
|
||||
const data = await response.json()
|
||||
const allItems = [...(data.unlocked || []), ...(data.locked || [])]
|
||||
const count = data.completed_count || 0
|
||||
|
||||
|
||||
// Проверяем, что пользователь не переключился на другую доску пока шёл запрос
|
||||
if (selectedBoardIdRef.current !== boardId) return
|
||||
|
||||
setItems(allItems)
|
||||
setCompletedCount(count)
|
||||
saveItemsToCache(selectedBoardId, allItems, count)
|
||||
saveItemsToCache(boardId, allItems, count)
|
||||
setError('')
|
||||
} catch (err) {
|
||||
if (selectedBoardIdRef.current !== boardId) return
|
||||
setError(err.message)
|
||||
if (!loadItemsFromCache(selectedBoardId)) {
|
||||
if (!loadItemsFromCache(boardId)) {
|
||||
setItems([])
|
||||
setCompletedCount(0)
|
||||
}
|
||||
} finally {
|
||||
setLoading(false)
|
||||
if (selectedBoardIdRef.current === boardId) {
|
||||
setLoading(false)
|
||||
}
|
||||
fetchingRef.current = false
|
||||
}
|
||||
}
|
||||
|
||||
// Загрузка завершённых для текущей доски
|
||||
const fetchCompleted = async () => {
|
||||
if (fetchingCompletedRef.current || !selectedBoardId) return
|
||||
const fetchCompleted = async (boardId) => {
|
||||
if (fetchingCompletedRef.current || !boardId) return
|
||||
fetchingCompletedRef.current = true
|
||||
|
||||
|
||||
try {
|
||||
setCompletedLoading(true)
|
||||
// Используем новый API для получения завершённых на доске
|
||||
const response = await authFetch(`${API_URL}/boards/${selectedBoardId}/completed`)
|
||||
|
||||
const response = await authFetch(`${API_URL}/boards/${boardId}/completed`)
|
||||
|
||||
if (!response.ok) {
|
||||
const errText = await response.text()
|
||||
const msg = errText || 'Ошибка при загрузке завершённых желаний'
|
||||
throw new Error(msg)
|
||||
}
|
||||
|
||||
|
||||
const data = await response.json()
|
||||
const completedData = Array.isArray(data) ? data : []
|
||||
|
||||
// Проверяем, что пользователь не переключился на другую доску пока шёл запрос
|
||||
if (selectedBoardIdRef.current !== boardId) return
|
||||
|
||||
setCompleted(completedData)
|
||||
} catch (err) {
|
||||
console.error('Error fetching completed items:', err)
|
||||
setCompleted([])
|
||||
if (selectedBoardIdRef.current === boardId) {
|
||||
setCompleted([])
|
||||
}
|
||||
} finally {
|
||||
setCompletedLoading(false)
|
||||
if (selectedBoardIdRef.current === boardId) {
|
||||
setCompletedLoading(false)
|
||||
}
|
||||
fetchingCompletedRef.current = false
|
||||
}
|
||||
}
|
||||
@@ -292,7 +308,7 @@ function Wishlist({ onNavigate, refreshTrigger = 0, isActive = false, initialBoa
|
||||
}
|
||||
|
||||
// Загружаем свежие данные
|
||||
fetchItems()
|
||||
fetchItems(selectedBoardId)
|
||||
}
|
||||
}, [selectedBoardId])
|
||||
|
||||
@@ -300,13 +316,13 @@ function Wishlist({ onNavigate, refreshTrigger = 0, isActive = false, initialBoa
|
||||
useEffect(() => {
|
||||
const wasActive = prevIsActiveRef.current
|
||||
prevIsActiveRef.current = isActive
|
||||
|
||||
|
||||
if (!initialFetchDoneRef.current) return
|
||||
|
||||
|
||||
if (isActive && !wasActive) {
|
||||
fetchBoards()
|
||||
if (selectedBoardId) {
|
||||
fetchItems()
|
||||
fetchItems(selectedBoardId)
|
||||
}
|
||||
}
|
||||
}, [isActive])
|
||||
@@ -321,9 +337,9 @@ function Wishlist({ onNavigate, refreshTrigger = 0, isActive = false, initialBoa
|
||||
console.error('Error clearing cache:', err)
|
||||
}
|
||||
fetchBoards()
|
||||
fetchItems()
|
||||
fetchItems(selectedBoardId)
|
||||
if (completedExpanded && completedCount > 0) {
|
||||
fetchCompleted()
|
||||
fetchCompleted(selectedBoardId)
|
||||
}
|
||||
}
|
||||
}, [refreshTrigger, selectedBoardId])
|
||||
@@ -421,7 +437,7 @@ function Wishlist({ onNavigate, refreshTrigger = 0, isActive = false, initialBoa
|
||||
setCompletedExpanded(newExpanded)
|
||||
|
||||
if (newExpanded && completedCount > 0) {
|
||||
fetchCompleted()
|
||||
fetchCompleted(selectedBoardId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,9 +481,9 @@ function Wishlist({ onNavigate, refreshTrigger = 0, isActive = false, initialBoa
|
||||
}
|
||||
|
||||
setSelectedItem(null)
|
||||
await fetchItems()
|
||||
await fetchItems(selectedBoardId)
|
||||
if (completedExpanded) {
|
||||
await fetchCompleted()
|
||||
await fetchCompleted(selectedBoardId)
|
||||
}
|
||||
} catch (err) {
|
||||
setError(err.message)
|
||||
@@ -502,8 +518,8 @@ function Wishlist({ onNavigate, refreshTrigger = 0, isActive = false, initialBoa
|
||||
}
|
||||
|
||||
// Обновляем список
|
||||
await fetchItems()
|
||||
|
||||
await fetchItems(selectedBoardId)
|
||||
|
||||
// Открываем форму редактирования для нового желания
|
||||
onNavigate?.('wishlist-form', { wishlistId: newItem.id, boardId: selectedBoardId })
|
||||
} catch (err) {
|
||||
@@ -682,7 +698,7 @@ function Wishlist({ onNavigate, refreshTrigger = 0, isActive = false, initialBoa
|
||||
loading={boardsLoading}
|
||||
showBoardAction={false}
|
||||
/>
|
||||
<LoadingError onRetry={() => fetchItems()} />
|
||||
<LoadingError onRetry={() => fetchItems(selectedBoardId)} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -794,9 +810,9 @@ function Wishlist({ onNavigate, refreshTrigger = 0, isActive = false, initialBoa
|
||||
onNavigate={onNavigate}
|
||||
boardId={selectedBoardId}
|
||||
onRefresh={async () => {
|
||||
await fetchItems()
|
||||
await fetchItems(selectedBoardId)
|
||||
if (completedExpanded) {
|
||||
await fetchCompleted()
|
||||
await fetchCompleted(selectedBoardId)
|
||||
}
|
||||
}}
|
||||
onClose={handleCloseDetail}
|
||||
|
||||
Reference in New Issue
Block a user