fix: Resolve infinite render loop by memoizing context functions and values

This commit is contained in:
Yunxiao Xu
2026-02-17 02:43:19 -08:00
parent 23471350df
commit 1b15a4e18c
2 changed files with 40 additions and 26 deletions

View File

@@ -1,4 +1,4 @@
import { useState, useEffect, createContext, useContext } from "react"
import { useState, useEffect, createContext, useContext, useMemo, useCallback } from "react"
import { Routes, Route } from "react-router-dom"
import { MainLayout } from "./components/layout/MainLayout"
import { LoginForm } from "./components/auth/LoginForm"
@@ -25,8 +25,15 @@ function AuthProvider({ children }: { children: React.ReactNode }) {
const [isAuthenticated, setIsAuthenticated] = useState(false)
const [user, setUser] = useState<UserResponse | null>(null)
const value = useMemo(() => ({
isAuthenticated,
setIsAuthenticated,
user,
setUser
}), [isAuthenticated, user])
return (
<AuthContext.Provider value={{ isAuthenticated, setIsAuthenticated, user, setUser }}>
<AuthContext.Provider value={value}>
{children}
</AuthContext.Provider>
)
@@ -81,16 +88,16 @@ function AppContent() {
initAuth()
}, [setIsAuthenticated, setThemeLocal, setUser])
const loadHistory = async () => {
const loadHistory = useCallback(async () => {
try {
const history = await ChatService.listConversations()
setConversations(history)
} catch (err) {
console.error("Failed to load conversation history:", err)
}
}
}, [])
const handleAuthSuccess = async () => {
const handleAuthSuccess = useCallback(async () => {
try {
const userData = await AuthService.getMe()
setUser(userData)
@@ -102,9 +109,9 @@ function AppContent() {
} catch (err: unknown) {
console.error("Failed to fetch user profile after login:", err)
}
}
}, [setUser, setIsAuthenticated, setThemeLocal, loadHistory])
const handleLogout = async () => {
const handleLogout = useCallback(async () => {
try {
await AuthService.logout()
} catch (err: unknown) {
@@ -117,9 +124,9 @@ function AppContent() {
setThreadMessages({})
setThemeLocal("light")
}
}
}, [setIsAuthenticated, setUser, setThemeLocal])
const handleSelectConversation = async (id: string) => {
const handleSelectConversation = useCallback(async (id: string) => {
setSelectedThreadId(id)
try {
const msgs = await ChatService.getMessages(id)
@@ -127,9 +134,9 @@ function AppContent() {
} catch (err) {
console.error("Failed to fetch messages:", err)
}
}
}, [])
const handleCreateConversation = async () => {
const handleCreateConversation = useCallback(async () => {
try {
const newConv = await ChatService.createConversation()
setConversations(prev => [newConv, ...prev])
@@ -138,18 +145,18 @@ function AppContent() {
} catch (err) {
console.error("Failed to create conversation:", err)
}
}
}, [])
const handleRenameConversation = async (id: string, name: string) => {
const handleRenameConversation = useCallback(async (id: string, name: string) => {
try {
const updated = await ChatService.renameConversation(id, name)
setConversations(prev => prev.map(c => c.id === id ? updated : c))
} catch (err) {
console.error("Failed to rename conversation:", err)
}
}
}, [])
const handleDeleteConversation = async (id: string) => {
const handleDeleteConversation = useCallback(async (id: string) => {
try {
await ChatService.deleteConversation(id)
setConversations(prev => prev.filter(c => c.id !== id))
@@ -164,11 +171,11 @@ function AppContent() {
} catch (err) {
console.error("Failed to delete conversation:", err)
}
}
}, [selectedThreadId])
const handleMessagesFinal = (id: string, messages: MessageResponse[]) => {
const handleMessagesFinal = useCallback((id: string, messages: MessageResponse[]) => {
setThreadMessages(prev => ({ ...prev, [id]: messages }))
}
}, [])
const queryParams = new URLSearchParams(window.location.search)
const externalError = queryParams.get("error")