React Router Dom条件渲染:如何向Hero组件传递路由状态
Hey there! Let's break down how to get your current route info into that reusable Hero component, and fix a few syntax/structure issues in your existing code along the way.
First, Fix Your App Structure
Right now, you've nested a Router inside your Hero component—this is a problem because your app should only have one top-level Router (usually in your root App component). Having multiple Routers will cause routing context conflicts, and your route-related hooks won't work as expected. Let's restructure that first:
// App.js (your root component) import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'; import Navbar from './Navbar'; import Home from './Home'; import Consultants from './Consultants'; import Solutions from './Solutions'; import ContactUs from './ContactUs'; function App() { return ( <Router> <Navbar /> {/* Move Navbar here—it's a global component, not part of Hero */} <Switch> <Route exact path='/' component={Home} /> <Route exact path='/consultants' component={Consultants} /> <Route exact path='/solutions' component={Solutions} /> <Route exact path='/contactus' component={ContactUs} /> </Switch> </Router> ); } export default App;
Option 1: Pass Route Info via Props (Simplest Approach)
The most straightforward way is to grab the current route in each page component, then pass it down to Hero as a prop.
- Update your page components (Home, Consultants, Solutions) to use
useLocationfromreact-router-dom:
// Home.js import { useLocation } from 'react-router-dom'; import Hero from './Hero'; function Home() { const location = useLocation(); return ( <div> <Hero currentPath={location.pathname} /> {/* Add your Home page content here */} </div> ); } export default Home;
Repeat this pattern for Consultants.js and Solutions.js—they'll look almost identical, just rendering their own content after the Hero.
- Refactor the Hero component to use the passed
currentPathprop:
// Hero.js import { Fragment, useEffect } from 'react'; // Import your images (adjust paths to match your project) import homeimg from './assets/home-hero.jpg'; import consimg from './assets/consultants-hero.jpg'; import solsimg from './assets/solutions-hero.jpg'; const Hero = ({ currentPath }) => { // Now this useEffect will trigger whenever the route changes useEffect(() => { console.log('Current route:', currentPath); }, [currentPath]); // Helper function to get the correct hero image const getHeroImage = () => { switch (currentPath) { case '/consultants': return consimg; case '/solutions': return solsimg; case '/': default: return homeimg; } }; // Helper function to get the correct grid class const getHeroClass = () => { switch (currentPath) { case '/consultants': return 'grid-consultants'; case '/solutions': return 'grid-solutions'; case '/': default: return 'grid-home'; } }; return ( <Fragment> <div className='grid-hero'> <div className='overlay'> <div> <p className='bg-dark'></p> <img src={getHeroImage()} alt={`Hero banner for ${currentPath === '/' ? 'Home' : currentPath.slice(1)}`} /> </div> </div> </div> <div className={getHeroClass()}> {/* Add your Hero's inner content here */} </div> </Fragment> ); }; export default Hero;
Option 2: Use React Context (For Scalability)
If you don't want to pass the route prop through every page component, you can create a global context to share route state across your app.
- Create a Route Context:
// RouteContext.js import { createContext, useContext, useLocation } from 'react'; const RouteContext = createContext(); export const RouteProvider = ({ children }) => { const location = useLocation(); return ( <RouteContext.Provider value={{ pathname: location.pathname }}> {children} </RouteContext.Provider> ); }; // Custom hook to access the route context export const useRoute = () => { return useContext(RouteContext); };
- Wrap your app with the RouteProvider:
// App.js import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'; import { RouteProvider } from './RouteContext'; // ... other imports function App() { return ( <Router> <RouteProvider> <Navbar /> <Switch> {/* Your routes stay the same */} </Switch> </RouteProvider> </Router> ); }
- Update Hero to use the custom hook:
// Hero.js import { Fragment, useEffect } from 'react'; import { useRoute } from './RouteContext'; // ... image imports const Hero = () => { const { pathname } = useRoute(); useEffect(() => { console.log('Current route:', pathname); }, [pathname]); // Reuse the same getHeroImage and getHeroClass functions from Option 1, using pathname instead of currentPath return ( {/* Same JSX as Option 1, using pathname to get image/class */} ); };
Key Fixes from Your Original Code
- Removed the nested
Routerin Hero (only one Router should exist at the top) - Fixed the invalid
imgsrc syntax (switched to a helper function to select the correct image) - Fixed the invalid className syntax (used a helper function to return the correct class based on route)
- Added
currentPath/pathnameto the useEffect dependency array so it triggers when the route changes
内容的提问来源于stack exchange,提问作者Mickey Gray

