前情提要:
nextjs同一个域名下配置子路由 - 掘金 (juejin.cn)
问题描述:
/admin登录的时候 会不导航到admin页面;然后在/admin/login这个路径登录就会导航到admin
before
没有登录的时候,url不会改变,仍然会是/admin 但是内容却是Login页面的内容
/admin页面
"use client";
import OrderForm from "../components/orderForm";
import { Suspense } from "react";
import Layout from "./(logout)/layout";
export default function Home() {
return (
<main className={" w-screen flex-col items-center "}>
<Suspense>
<Layout>//这个Layout里面包含了CheckLogin
<OrderForm />
</Layout>
</Suspense>
</main>
);
}
//CheckLogin
import React, { useEffect, useState } from "react";
import { checkToken } from "@/utils/token-storage";
import Login from "@/app/login/page";
import { useRouter } from "next/navigation";
const CheckLogin: React.FC<{ children: React.ReactNode }> = (props) => {
const [isLogin, setIsLogin] = useState(false);
const [checked, setChecked] = useState(false);
const navigate = useRouter();
useEffect(() => {
const loginStatus = checkToken();
setIsLogin(loginStatus==0?false:true);
setChecked(true);
}, [checkToken()]);
console.log("checkToken()",checkToken())
if (!checked) {
return null; // or a loading spinner
}
return (
<>
{isLogin ? props.children : <Login/>}
</>
);
};
export default CheckLogin;
Login组件 当我请求成功,handleNav("/"),仍然在/admin这个页面
const handleLogin = async () => {
try {
const res = await axios.post(`/login`, {
username: parentFormData?.username?.trim(),
password: parentFormData?.password?.trim(),
});
if (res?.data?.code === 100) {
setLoginRes(LoginRes.failed);
} else if (res?.data?.code === 200) {
setLoginRes(LoginRes.success);
storeToken(res?.data?.data);
setTimeout(() => handleNav("/"), 1500);//当我请求成功,handleNav("/"),仍然在/admin这个页面
}
} catch (err) {}
};
export const checkToken = () => {
let token = typeof window && getToken()
const now = new Date().getTime() / 1000
const expire = getExpire()
console.log(now, expire,token)//expire token即使在登录成功后,在也是null
if (!token || !expire || now >= +expire) return 0
return 1
}
但是刷新之后就可以正常进入系统 因为在登录之后在localstorage设置了token 再跳转到/admin 但是因为/admin状态都没有改变,checkToken()不会被重新调,所以就还是渲染Login组件
解决方法1
用导航的方式导航到login组件 这样子,在login页面登录成功就会跳转到/admin,重新挂载admin页面,就会再次调用checkToken,得到的就是1了
after
// admin
const navigate = useRouter();
useEffect(() => {
const loginStatus = checkToken();
setIsLogin(loginStatus==0?false:true);
setChecked(true);
}, []);
return (
<>
{isLogin ? props.children :navigate.push("/login")}
</>
);
};
解决方法2
使用Redux toolkit或其他状态管理,在Login组件登录成功的时候就dispatch状态,在admin页面监听这个状态