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

React Router 6:父组件调用子组件函数的问题及解决

问题与解决方案

需求描述

在MainHeader.js中,点击NavLink时,若当前路由为'/',则调用Home.js(子组件)中定义的testHandler函数,否则跳转到路由'/event'。

尝试的实现方案(未生效)

尝试通过forwardRef实现函数组件间的方法调用,但未成功,相关代码如下:

App.js

const router = createBrowserRouter([
  {
    path: '/',
    element: <MainHeader />, 
    children:[
      { index: true, element: <Home />, loader :loaderHome }, 
    ]
  }
])

const App = () => { 
  return <RouterProvider router={router} />; 
}

export default App;

MainHeader.js

import { Outlet, NavLink, useLocation } from 'react-router-dom';

const MainHeader = (props) => { 
  const testRef = useRef();
  const location = useLocation();
  return (
    <>
      <header className={styles['main-header']}>
        <NavLink to={location.pathname==='/' ? testRef.current.testHandler : '/event'}>
          Home3
        </NavLink>
        <Login />
      </header>
      <Outlet innerRef={testRef} />
    </>
  );
}

export default MainHeader;

Home.js

import React, { useRef, useImperativeHandle } from 'react';

const Home = React.forwardRef((props, ref) => {
  useImperativeHandle(ref, () => {
    return {
      testHandler: testHandler
    }
  })

  // 用useCallback避免useEffect触发时函数重新加载
  const testHandler=async(e)=>{
    console.log('enter test handler')
  }

  return (
    ............
  );
})

export default Home;

尝试在MainHeader.js的Outlet组件中传递ref到Home.js来调用testHandler函数,但未成功。请问是否需要修改App.js?或者有没有其他方式可以从MainHeader.js调用testHandler函数?

可行的解决代码(已验证有效)

以下是经过验证的修改方案:

App.js

const App=()=>{ 
  const mainHeaderToHomeRef=useRef();

  const router=createBrowserRouter([{
    path:'/',
    element: <MainHeader ref={mainHeaderToHomeRef} />, // 包裹下方所有子路由
    children:[
      {index:true, element:<Home ref={mainHeaderToHomeRef} />, loader:loaderHome }, // 索引路由 ./
    ]
  }])

  return <RouterProvider router={router} />; 
}

export default App;

MainHeader.js

import React from 'react';
import { Outlet, NavLink, useLocation } from 'react-router-dom';

const MainHeader=React.forwardRef((props, ref)=>{ 
    const location = useLocation();

    const homeHandleClick=(e)=>{
        if(location.pathname==='/' && ref.current){
            e.preventDefault() // 阻止链接跳转
            ref.current.homeHandler() // 调用Home.js中的函数
        }
    }

    return(
        <>
        <header className={styles['main-header']}>
            <h1>Rotten Tomatoes</h1>
            <NavLink to='/' onClick={homeHandleClick}>Home3</NavLink>
            <Login/>
        </header>
        {/* Outlet是子路由的渲染位置,对应App.js中的所有子组件 */}
        <Outlet/>
        </>
    );
})

export default MainHeader;

Home.js

import React, { useRef, useImperativeHandle } from 'react';

const Home = React.forwardRef((props, ref) => {
  useImperativeHandle(ref, () => {
    return{homeHandler:homeHandler}
  })
  
  // 用useCallback避免useEffect触发时函数重新加载
  const homeHandler=useCallback(async(e)=>{
        console.log('home handler entered')
    },[]);

  return (
    ............
  );
})

export default Home;

内容的提问来源于stack exchange,提问作者D. Rattansingh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 21:37:38