diff --git a/src/app/(main)/axios/AxiosProvider.tsx b/src/app/(main)/axios/AxiosProvider.tsx index 20832e8..9de6002 100644 --- a/src/app/(main)/axios/AxiosProvider.tsx +++ b/src/app/(main)/axios/AxiosProvider.tsx @@ -1,42 +1,67 @@ +// src/app/(main)/axios/AxiosProvider.tsx + "use client"; -import React, { createContext, useContext, useEffect, useState } from "react"; + +import React, { createContext, useContext, useEffect, useState, useCallback } from "react"; import axiosInstance, { SetupAxiosInterceptors } from "./axiosInstance"; const AxiosContext = createContext(axiosInstance); -const TokenContext = createContext({ - setAccessToken: (token: string | null) => {}, + +const TokenContext = createContext<{ + setAccessToken: (token: string | null) => void; +}>({ + setAccessToken: () => {}, }); -export const AxiosProvider: React.FC<{ children: React.ReactNode }> = ({ - children, -}) => { - const [accessToken, setAccessToken] = useState( - localStorage.getItem("accessToken"), - ); +export const AxiosProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const [accessToken, setAccessToken] = useState(null); + const [isHydrated, setIsHydrated] = useState(false); + + // Hydrate token only on client + useEffect(() => { + try { + const token = localStorage.getItem("accessToken"); + if (token) setAccessToken(token); + } catch (e) { + console.warn("localStorage unavailable", e); + } finally { + setIsHydrated(true); + } + }, []); + // Apply token + interceptors useEffect(() => { if (accessToken) { axiosInstance.defaults.headers.Authorization = `Bearer ${accessToken}`; SetupAxiosInterceptors(accessToken); - console.log("[debug] Updated accessToken:", accessToken); + } else { + delete axiosInstance.defaults.headers.Authorization; } }, [accessToken]); + const handleSetAccessToken = useCallback((token: string | null) => { + setAccessToken(token); + try { + if (token) { + localStorage.setItem("accessToken", token); + } else { + localStorage.removeItem("accessToken"); + } + } catch (e) { + // ignore (e.g. private mode) + } + }, []); + + // Critical fix: never return null → always return children wrapped in fragment return ( - + + {/* Render children immediately – they will just not have the token for 1-2ms */} {children} ); }; -// Custom hook to use Axios instance -export const useAxios = () => { - return useContext(AxiosContext); -}; - -// Custom hook to manage access token -export const useToken = () => { - return useContext(TokenContext); -}; +export const useAxios = () => useContext(AxiosContext); +export const useToken = () => useContext(TokenContext); \ No newline at end of file