fix: исправлена проблема с обновлением refresh token (race condition)
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 50s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 50s
- Добавлена синхронизация параллельных refresh-запросов - Исправлена проблема сброса авторизации на следующий день - Версия обновлена до 3.5.7
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "play-life-web",
|
||||
"version": "3.5.6",
|
||||
"version": "3.5.7",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { createContext, useContext, useState, useEffect, useCallback } from 'react'
|
||||
import React, { createContext, useContext, useState, useEffect, useCallback, useRef } from 'react'
|
||||
|
||||
const AuthContext = createContext(null)
|
||||
|
||||
@@ -10,6 +10,9 @@ export function AuthProvider({ children }) {
|
||||
const [user, setUser] = useState(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState(null)
|
||||
|
||||
// Ref для синхронизации параллельных refresh-запросов
|
||||
const refreshPromiseRef = useRef(null)
|
||||
|
||||
const logout = useCallback(async () => {
|
||||
const token = localStorage.getItem(TOKEN_KEY)
|
||||
@@ -34,7 +37,8 @@ export function AuthProvider({ children }) {
|
||||
setUser(null)
|
||||
}, [])
|
||||
|
||||
const refreshToken = useCallback(async () => {
|
||||
// Внутренняя функция для выполнения refresh
|
||||
const doRefreshToken = useCallback(async () => {
|
||||
const refresh = localStorage.getItem(REFRESH_TOKEN_KEY)
|
||||
|
||||
if (!refresh) {
|
||||
@@ -84,6 +88,25 @@ export function AuthProvider({ children }) {
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Синхронизированная функция refresh - предотвращает race condition
|
||||
// Если refresh уже выполняется, все вызовы ждут его завершения
|
||||
const refreshToken = useCallback(async () => {
|
||||
// Если refresh уже выполняется, ждём его завершения
|
||||
if (refreshPromiseRef.current) {
|
||||
console.log('[Auth] Refresh already in progress, waiting...')
|
||||
return refreshPromiseRef.current
|
||||
}
|
||||
|
||||
// Создаём promise для refresh и сохраняем его
|
||||
console.log('[Auth] Starting token refresh...')
|
||||
refreshPromiseRef.current = doRefreshToken().finally(() => {
|
||||
// Очищаем ref после завершения (успешного или нет)
|
||||
refreshPromiseRef.current = null
|
||||
})
|
||||
|
||||
return refreshPromiseRef.current
|
||||
}, [doRefreshToken])
|
||||
|
||||
// Initialize from localStorage
|
||||
useEffect(() => {
|
||||
const initAuth = async () => {
|
||||
|
||||
Reference in New Issue
Block a user