Fix React error #130 - Remove authentication race condition

- Remove setTimeout delays in AdminAuthContext login function
- Make authentication state updates synchronous
- Replace setTimeout navigation with state-based navigation in AdminLoginPage
- Add proper error handling and component lifecycle management in CreateEventPage
- Prevent navigation if component unmounts during async operations

This fixes the issue where users would see React error #130 during login
and couldn't create events or save settings.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-07-07 13:12:39 +02:00
parent 9dd643338b
commit 2e10374e2c
3 changed files with 40 additions and 26 deletions
+13 -10
View File
@@ -36,13 +36,19 @@ export const AdminAuthProvider: React.FC<AdminAuthProviderProps> = ({ children }
useEffect(() => {
// Check if user has a valid token on mount
const checkAuth = async () => {
const token = getAuthToken(true);
if (token) {
// For now, just assume the token is valid
// TODO: Validate token with backend and get user info
setIsAuthenticated(true);
try {
const token = getAuthToken(true);
if (token) {
// For now, just assume the token is valid
// TODO: Validate token with backend and get user info
setIsAuthenticated(true);
}
} catch (error) {
console.error('Auth check error:', error);
setError('Failed to check authentication');
} finally {
setIsLoading(false);
}
setIsLoading(false);
};
checkAuth();
@@ -52,10 +58,7 @@ export const AdminAuthProvider: React.FC<AdminAuthProviderProps> = ({ children }
// Token is already stored in cookie by authService
setUser(user);
setError(null);
// Small delay to ensure state is properly updated
setTimeout(() => {
setIsAuthenticated(true);
}, 100);
setIsAuthenticated(true);
};
const logout = () => {
+6 -11
View File
@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { useNavigate, Navigate } from 'react-router-dom';
import { Navigate } from 'react-router-dom';
import { Lock, Mail, Eye, EyeOff, AlertCircle } from 'lucide-react';
import { toast } from 'react-toastify';
@@ -9,7 +9,6 @@ import { authService } from '../../services/auth.service';
import { getAuthToken } from '../../config/api';
export const AdminLoginPage: React.FC = () => {
const navigate = useNavigate();
const { isAuthenticated, login } = useAdminAuth();
const [formData, setFormData] = useState({
@@ -19,9 +18,10 @@ export const AdminLoginPage: React.FC = () => {
const [showPassword, setShowPassword] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [errors, setErrors] = useState<Record<string, string>>({});
const [loginSuccess, setLoginSuccess] = useState(false);
// Redirect if already authenticated
if (isAuthenticated) {
// Redirect if already authenticated or login successful
if (isAuthenticated || loginSuccess) {
return <Navigate to="/admin/dashboard" replace />;
}
@@ -58,10 +58,7 @@ export const AdminLoginPage: React.FC = () => {
const response = await authService.adminLogin(formData);
login(response.token, response.user);
toast.success('Login successful!');
// Add a small delay to ensure auth state is updated
setTimeout(() => {
navigate('/admin/dashboard');
}, 200);
setLoginSuccess(true);
} catch (error: any) {
console.error('Login error:', error);
@@ -71,9 +68,7 @@ export const AdminLoginPage: React.FC = () => {
const token = getAuthToken(true);
if (token) {
// Login was successful, just had a connection issue
setTimeout(() => {
navigate('/admin/dashboard');
}, 200);
setLoginSuccess(true);
return;
}
toast.error('Network error. Please check your connection and try again.');
+21 -5
View File
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useState, useRef, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import {
Calendar,
@@ -45,6 +45,13 @@ const COLOR_THEMES = [
export const CreateEventPage: React.FC = () => {
const navigate = useNavigate();
const isMountedRef = useRef(true);
useEffect(() => {
return () => {
isMountedRef.current = false;
};
}, []);
const [formData, setFormData] = useState<FormData>({
event_type: 'wedding',
@@ -65,18 +72,27 @@ export const CreateEventPage: React.FC = () => {
const createMutation = useMutation({
mutationFn: eventsService.createEvent,
onSuccess: (data) => {
toast.success('Event created successfully!');
navigate(`/admin/events/${data.id}`);
if (isMountedRef.current) {
toast.success('Event created successfully!');
navigate(`/admin/events/${data.id}`);
}
},
onError: (error: any) => {
if (error.response?.data?.errors) {
if (!isMountedRef.current) return;
if (error.code === 'ERR_NETWORK' || error.code === 'ERR_CONNECTION_RESET') {
toast.error('Network error. Please check your connection and try again.');
} else if (error.response?.data?.errors) {
const newErrors: Record<string, string> = {};
error.response.data.errors.forEach((err: any) => {
newErrors[err.path] = err.msg;
});
setErrors(newErrors);
} else if (error.response?.status === 401) {
toast.error('Session expired. Please login again.');
navigate('/admin/login');
} else {
toast.error('Failed to create event');
toast.error(error.response?.data?.error || 'Failed to create event');
}
},
});