You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React嵌套路由问题:子组件跳转后父路由未激活加载

问题与解决方案

路由结构代码

index.js

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    
    <AuthFBContextProvider>
            <LangContextProvider>
                <BrowserRouter>
                    <App />
                </BrowserRouter>
            </LangContextProvider>
    </AuthFBContextProvider>
);

App.js

return (
        <Switch>
          {/* <Route path='/' exact>
            <Redirect to='/en' />
          </Route> */}
          <Route path='/en'>
            <EnglishRouter />
          </Route>
          <Route path="/fr">
            <FrenchRouter/>
          </Route>
          <Route path='*'>
            <NotFound />
          </Route>
        </Switch>
);

EnglishRouter.js(父组件,仅在/en路径渲染)

<MainNavigation>
        <p>english route</p>
        <Switch>
            <Route path={path} exact>
                <MainPage />  
            </Route>
            <Route path={`${path}/promotions`} exact> {/* 对应路由 en/promotions */}
                <Promotions />
            </Route>
            <Route path={`${path}/auth`}> {/* 对应路由 en/auth */}
                <AuthPage />
            </Route>
        </Switch>
    </MainNavigation>)

AuthPage.js(子组件,在en/auth路径渲染)

<Router>
      <Switch>
        <Route path={`${path}/signup`} component={Signup} exact/>
        <Route path={`${path}/login`} component={Login} exact/>
        <Route path={`${path}/forgot-password`} component={ForgotPassword} exact/>
      </Switch>
    </Router>

Login.js

const Login = () => {
    const authFBCtx = useContext(AuthFBContext);
    const { path, url } = useRouteMatch()
    const history = useHistory();

    const submitHandler = (event) => {
        event.preventDefault();
    
        const enteredEmail = emailInputRef.current.value;
        const enteredPassword = passwordInputRef.current.value;
        authFBCtx.login(enteredEmail, enteredPassword);
        history.push('en/promotions')
      }

    return(...<form onSubmit={submitHandler}></form>)
}

问题描述

登录后调用history.push('en/promotions'),URL显示正确但Promotions组件不加载;手动在AuthPage.js添加对应路由后组件能嵌套渲染,但父组件EnglishRouter的导航NavLink仍显示/en/auth为激活状态。需要实现跳转触发父组件路由更新,同步导航激活状态。

解决方案

1. 移除AuthPage中的多余<Router>组件

React Router的路由上下文是从上到下继承的,AuthPage已经被外层的BrowserRouter包裹,不需要再嵌套<Router>。多余的Router会创建独立的路由上下文,导致内部的路由操作无法同步到外层路由,这就是跳转后父组件路由不更新的核心原因。

修改后的AuthPage.js:

<Switch>
  <Route path={`${path}/signup`} component={Signup} exact/>
  <Route path={`${path}/login`} component={Login} exact/>
  <Route path={`${path}/forgot-password`} component={ForgotPassword} exact/>
</Switch>

2. 使用正确的路径格式跳转

在Login.js中,建议使用绝对路径或者基于useRouteMatch返回的url构造目标路径,避免路径解析错误:

// 方式1:直接使用绝对路径
history.push('/en/promotions')

// 方式2:基于当前语言路由的相对路径(适配多语言场景)
const { url } = useRouteMatch();
history.push(`${url.split('/auth')[0]}/promotions`)

3. 修正导航NavLink的激活逻辑

检查MainNavigation中的NavLink,确保to属性为正确的绝对路径,若存在嵌套路由场景,可通过isActive自定义激活判断逻辑,确保父级导航在跳转后能正确取消激活:

<NavLink 
  to="/en/auth" 
  isActive={(match, location) => {
    // 仅当路径以/en/auth开头且不属于其他路由时激活
    return location.pathname.startsWith('/en/auth') && !location.pathname.startsWith('/en/promotions');
  }}
>
  Auth
</NavLink>

内容的提问来源于stack exchange,提问作者masafood

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 23:36:22