React useState结合if else判断URL参数触发too many renders报错如何解决
错误原因
代码直接在组件渲染流程的顶层调用state更新方法setLeftHeader,每次调用setLeftHeader都会触发组件重新渲染,重新渲染时又会再次执行顶层的判断逻辑、再次触发setLeftHeader,由此形成无限循环,触发React的重渲染次数限制报错。
最优修复方案
leftHeader的值完全可以通过当前URL直接计算得到,属于派生状态,不需要用state存储,直接计算即可彻底消除无限循环问题:
export default function Navbar() { const href = window.location.href let leftHeader = "ff" if (href.includes("/admin/aa")) leftHeader = "aa" else if (href.includes("/admin/bb")) leftHeader = "bb" else if (href.includes("/admin/cc")) leftHeader = "cc" else if (href.includes("/admin/dd")) leftHeader = "dd" else if (href.includes("/admin/ee")) leftHeader = "ee" return ( <> {/* Navbar */} <nav className="absolute top-0 left-0 w-full z-10 bg-transparent md:flex-row md:flex-nowrap md:justify-start flex items-center p-4"> <div className="w-full mx-autp items-center flex justify-between md:flex-nowrap flex-wrap md:px-12 px-4"> {/* Brand */} <a className="text-white text-xl uppercase hidden lg:inline-block font-semibold" href="#pablo" onClick={(e) => e.preventDefault()} > {leftHeader} </a> <ul className="flex-col md:flex-row list-none items-center hidden md:flex"> <UserDropdown /> </ul> </div> </nav> {/* End Navbar */} </> ) }
备选方案(需要保留state的场景)
如果后续需要在组件内手动修改leftHeader的值,必须保留state的话,可以将更新逻辑包裹在useEffect中,仅在URL发生变化时才执行状态更新:
import { useState, useEffect } from 'react' export default function Navbar() { const [leftHeader, setLeftHeader] = useState("aa"); useEffect(() => { const href = window.location.href if (href.includes("/admin/aa")) { console.log("aa"); setLeftHeader("aa"); } else if (href.includes("/admin/bb")) { console.log("bb"); setLeftHeader("bb"); } else if (href.includes("/admin/cc")) { console.log("cc"); setLeftHeader("cc"); } else if (href.includes("/admin/dd")) { console.log("dd"); setLeftHeader("dd"); } else if (href.includes("/admin/ee")) { console.log("ee"); setLeftHeader("ee"); } else { console.log("ff"); setLeftHeader("ff"); } }, [window.location.href]) return ( <> {/* Navbar */} <nav className="absolute top-0 left-0 w-full z-10 bg-transparent md:flex-row md:flex-nowrap md:justify-start flex items-center p-4"> <div className="w-full mx-autp items-center flex justify-between md:flex-nowrap flex-wrap md:px-12 px-4"> {/* Brand */} <a className="text-white text-xl uppercase hidden lg:inline-block font-semibold" href="#pablo" onClick={(e) => e.preventDefault()} > {leftHeader} </a> <ul className="flex-col md:flex-row list-none items-center hidden md:flex"> <UserDropdown /> </ul> </div> </nav> {/* End Navbar */} </> ); }
优化提示
如果你项目中使用了React Router,建议用useLocation()钩子获取路径,比直接监听window.location.href更适配React的响应式更新逻辑。
内容的提问来源于stack exchange,提问作者Leo S
相关产品推荐
相关产品推荐

