ReactJS/NextJS中useState触发标签页崩溃问题求助
问题分析与解决方案
核心问题
标签页冻结+路由报错的根源有两点:
- 组件每次渲染都会重复绑定
auth.onAuthStateChanged监听,状态更新触发重新渲染后又会再次绑定监听,形成无限循环,最终导致页面冻结。 router.push在服务器端渲染(SSR)阶段被调用,此时Next.js的router实例尚未初始化,触发"No router instance found"错误。
解决方案
步骤1:用useEffect包裹auth监听,避免重复绑定
将auth状态监听逻辑放到useEffect中,设置空依赖数组确保仅在组件挂载时绑定一次,同时添加清理函数避免内存泄漏:
import {useRouter} from "next/router"; import React, {useState, useEffect} from "react"; import {BsArrowDownCircle} from "react-icons/bs"; import {auth} from "./../../firebase"; import { ToastContainer, toast } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; export default function uploadFiles() { const router = useRouter(); const [loggedIn, setLoggedIn] = useState(false); const [openAddFolders, setOpenAddFolders] = useState(false); useEffect(() => { // 绑定auth状态监听 const unsubscribe = auth.onAuthStateChanged(function(user) { if (user) { setLoggedIn(true); }else{ toast.error("Please Sign In, You Are Being Redirected"); setTimeout(function(){ // 仅在客户端执行路由跳转 if (typeof window !== 'undefined') { router.push("/"); } }, 5000); } }); // 组件卸载时移除监听 return unsubscribe; }, [router, toast]); function openAddFoldersMenu() { setOpenAddFolders(true); } function openUploadImagesMenu() { console.log("b"); } return( <React.Fragment> <ToastContainer /> {loggedIn ? <div className="flex items-center justify-center"> <div className="w-1/2"> <div onClick={openAddFoldersMenu} className="hover:cursor-pointer my-10 rounded-t-3xl w-full p-9 hover:bg-cyan-400 hover:text-white hover:shadow-cyan-500/50 shadow-lg ease-linear duration-100"> <div className="flex justify-between"> <h1>Add Folders</h1> <BsArrowDownCircle className="animate-bounce" size={20} /> </div> {/* <div className={addFolders ? "" : "hidden"}> Some Information </div> */} </div> <div onClick={() => openUploadImagesMenu()} className="hover:cursor-pointer rounded-t-3xl w-full p-9 hover:bg-cyan-400 hover:text-white hover:shadow-cyan-500/50 shadow-lg ease-linear duration-100"> <div className="flex justify-between"> <h1>Upload Images</h1> <BsArrowDownCircle className="animate-bounce" size={20} /> </div> <div className="hidden"> Some Information </div> </div> </div> </div> : <div className="w-[100vw] h-[100vh] bg-red-500 flex items-center justify-center"> <h1 className="text-gray-50 text-7xl text-center">There Was A Problem Loading, <br /> Please Sign In</h1> </div> } </React.Fragment> ); };
步骤2:确保路由跳转仅在客户端执行
在router.push前添加typeof window !== 'undefined'判断,避免在服务器端调用客户端路由方法,彻底解决"No router instance found"错误。
修改后,auth监听只会绑定一次,不会引发无限循环;路由跳转仅在客户端执行,setOpenAddFolders(true)也能正常触发状态更新,页面冻结问题即可解决。
内容的提问来源于stack exchange,提问作者user19474938
相关产品推荐
相关产品推荐

