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
相关产品推荐
相关产品推荐

