Localstorage with client component
Unanswered
Great black wasp posted this in #help-forum
Great black waspOP
Hi, i want to fetch jwt token from localstorage and pass it to client component by useToken hook. What am i doing wrong? It just keeps me redirecting to /login
Any ideas?
I will paste hook under question, in comment
Any ideas?
"use client";
import { useHasMounted } from "@/hooks/useMountedHook";
import { useToken } from "@/hooks/useToken";
import { useRouter } from "next/navigation"; // Use "next/router" instead of "next/navigation"
import React, { useEffect } from "react";
function App() {
const navigation = useRouter();
const token = useToken();
const mounted = useHasMounted();
useEffect(() => {
if (!mounted) return;
if (!token) {
navigation.push("/login");
}
}, [mounted, token]);
return <div>{token}</div>;
}
export default App;I will paste hook under question, in comment
4 Replies
Great black waspOP
import { apiUrl } from "@/constants";
import axios, { AxiosError } from "axios";
import { useState } from "react";
const useToken = () => {
if (typeof window === "undefined") {
return;
}
const [token, setToken] = useState<string | null>(null);
const accessToken = localStorage.getItem("accessToken");
const refreshToken = localStorage.getItem("refreshToken");
if (refreshToken === null) return null;
if (accessToken === null && refreshToken !== null) {
//inline async function
(async () => {
try {
const response = await axios.post(`${apiUrl}/account/refresh`, {
refreshToken,
});
if (response.status === 200) {
setToken(response.data.token);
localStorage.setItem("accessToken", response.data.token);
}
} catch (err) {
return null;
}
})();
}
if (accessToken !== null) {
(async () => {
try {
const response = await axios.get(`${apiUrl}/account`, {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
if (response.status === 200) {
setToken(accessToken);
}
} catch (err) {
const error = err as AxiosError;
if (error.response?.status === 401) {
localStorage.removeItem("accessToken");
const response = await axios.post(`${apiUrl}/account/refresh`, {
refreshToken,
});
if (response.status === 200) {
localStorage.setItem("accessToken", response.data.token);
setToken(response.data.token);
}
}
}
})();
}
return token;
};
export { useToken };1. you shouldn't call hooks conditionally
2. side effects should be done inside
3. you can't access
4.
2. side effects should be done inside
useEffect, not in the root of hooks3. you can't access
localStorage in the root of a hook since it runs in the server, you must do it inside useEffect as it only runs in the browser4.
useEffect is called after the component is mounted, this check for useHasMounted doesn't really make senseGreat black waspOP
2. So i should not create that hook (useToken)?
you can as long as you follow the rule of hooks, you need to add at least one
useEffect to your custom hook to properly handle this logic