React无React Router时window.location.pathname二级路由组件不渲染问题
React 多级路径路由渲染故障解答
关于pathname的多级路径支持
window.location.pathname 原生完整支持多级路径段,它会返回URL域名后从首个/起始的完整路径字符串,无论路径包含多少层/分隔的段都可以正常读取,本次故障和pathname本身的能力无关。
故障核心原因
当前实现的两层路由判断均为全路径精确匹配,存在两个致命逻辑错误:
- App层的switch逻辑仅在路径完全等于
/PortfolioMain时才会挂载PortfolioMain组件。点击二级导航跳转到/PortfolioMain/Navigator这类带二级路径段的地址时,App层匹配不到任何case,component变量为undefined,主内容区域直接为空,PortfolioMain组件本身都不会渲染,自然看不到导航栏和目标内容。
另外App根路径/的case配置为渲染<App />,会触发组件递归渲染自身,属于明显的逻辑错误。 - 即便App层匹配逻辑正常,PortfolioMain内部的switch也没有覆盖导航栏中全部二级路径(
/PortfolioMain/AverSlides等三个路径未配置对应case),匹配失败时Current_slides为undefined,React渲染未定义组件会直接抛出运行时错误,导致整个组件树卸载。
修复方案
修正App层路由匹配
调整App组件的switch逻辑,增加前缀匹配规则,所有以/PortfolioMain开头的路径都渲染PortfolioMain组件,同时修正根路径的递归错误:
let component switch (window.location.pathname) { case "/": case "/Home": component = <Home />; break case "/About": component = <About />; break case "/Contact": component = <Contact />; break default: // 匹配作品集模块下所有多级路径 if (window.location.pathname.startsWith("/PortfolioMain")) { component = <PortfolioMain />; } break }
补全PortfolioMain层路由匹配
补全所有二级导航对应的路径case,增加默认兜底项,避免渲染未定义组件报错:
import RMSPortfolioSlides from './RMSPortfolioSlides'; import CLPortfolioSlides from './CLPortfolioSlides'; // 引入其余幻灯片对应组件 const PortfolioMain = props => { let Current_slides const currentPath = window.location.pathname switch (currentPath) { case "/PortfolioMain": case "/PortfolioMain/CLSlideshow": Current_slides = CLPortfolioSlides; break case "/PortfolioMain/Navigator": Current_slides = RMSPortfolioSlides break case "/PortfolioMain/AverSlides": // 替换为Aver模块对应的实际幻灯片组件 Current_slides = CLPortfolioSlides break case "/PortfolioMain/EnrollSlides": // 替换为报名模块对应的实际幻灯片组件 Current_slides = CLPortfolioSlides break case "/PortfolioMain/MobileAppSlides": // 替换为移动端模块对应的实际幻灯片组件 Current_slides = CLPortfolioSlides break default: // 兜底默认组件,避免匹配失败导致崩溃 Current_slides = CLPortfolioSlides } return ( <div className="portfolio_content"> <div className="current_slide_container"> <Current_slides /> </div> <div className='portfolio_navigation'> <nav className="portfolio_nav_container"> <ul className="portfolio_list"> <li><a href="/PortfolioMain/Navigator" className="port_nav_link">RMS1</a></li> <li><a href="/PortfolioMain/CLSlideshow" className="port_nav_link">CL</a></li> <li><a href="/PortfolioMain/AverSlides" className="port_nav_link">AVER</a></li> <li><a href="/PortfolioMain/EnrollSlides" className="port_nav_link">E-REG</a></li> <li><a href="/PortfolioMain/MobileAppSlides" className="port_nav_link">MOBILE</a></li> </ul> </nav> </div> </div> ); } export default PortfolioMain;
可选优化
当前使用原生<a>标签跳转会触发浏览器整页刷新,如果需要实现无刷新的前端路由效果,可以将当前路径存入React state,同时监听window的popstate事件,路径变化时更新state触发组件重渲染,无需引入React Router即可实现基础路由能力。
内容的提问来源于stack exchange,提问作者Keith Lavoie
相关产品推荐
相关产品推荐

