React实现跨组件点击链接打开指定Tab并支持URL哈希定位
Got it, let's walk through how to implement this feature so your links open the right tab in a new page, and shared URLs land directly on the correct tab too. The core idea is using URL hashes to pass the tab identifier, then having your PlatformFeatures component react to that hash on load and when it changes.
Step 1: Update Platform Component Links with Hashes
First, we need to fix the Platform component to receive the routes prop from HomePage and generate links with proper hashes pointing to the PlatformFeatures route. Each link will append a hash like #tab-{id} to specify which tab to open.
import React from 'react'; import PropTypes from 'prop-types'; import { I18nText } from '@wtag/react-comp-lib'; import profile from 'affiliateImages/person-24px.svg'; import search from 'affiliateImages/search-24px.svg'; import booking from 'affiliateImages/flight-24px.svg'; const Platform = ({ routes }) => { // Get the PlatformFeatures route path from props (fallback to a default path if needed) const featuresRoutePath = routes?.features?.platform || '/platform-features'; const features = [ { id: 0, icon: profile, name: <I18nText id="homepage.features.profiles.title" />, description: <I18nText id="homepage.features.profiles.description" />, link: `${featuresRoutePath}#tab-0`, }, { id: 1, icon: search, name: <I18nText id="homepage.features.search.title" />, description: <I18nText id="homepage.features.search.description" />, link: `${featuresRoutePath}#tab-1`, }, { id: 2, icon: booking, name: <I18nText id="homepage.features.booking.title" />, description: <I18nText id="homepage.features.booking.description" />, link: `${featuresRoutePath}#tab-2`, }, ]; return ( <div className="homepage__platform-section"> <div className="container"> <div className="homepage__platform-section-header"> <I18nText id="homepage.features.header.title" /> </div> <div className="grid"> {features.map(({ icon, name, description, link, id }) => ( <div className="col-xlg-4 col-lg-4 col-md-6 col-sm-6 col-xs-12 col-xxs-12" key={id}> <div> <span> <img src={icon} alt="icon" className="homepage__platform-section-icon" /> </span> <span className="homepage__platform-section-name">{name}</span> </div> <div className="homepage__platform-section-description"> {description} </div> <div> {/* Add target="_blank" to open in new tab */} <a href={link} className="homepage__platform-section-link" target="_blank" rel="noopener noreferrer"> <I18nText id="homepage.features.read.link" /> </a> </div> </div> ))} </div> </div> </div> ); }; // Add prop validation for routes Platform.propTypes = { routes: PropTypes.shape({ features: PropTypes.shape({ platform: PropTypes.string, }), }), }; export default Platform;
Step 2: Modify PlatformFeatures to Handle Hash Navigation
Next, update PlatformFeatures to:
- Read the initial URL hash to set the correct tab on load
- Listen for hash changes to update the tab dynamically (for manual URL edits or shared links)
import React, { useState, useEffect } from 'react'; import { RTabs, I18nText } from '@wtag/react-comp-lib'; import Profiles from './Profiles'; import Search from './Search'; import Booking from './Booking'; const features = [ { tabNum: 0, title: ( <I18nText id="features.platform.profiles" className="platform-features__profiles-tab" /> ), content: <Profiles />, }, { tabNum: 1, title: ( <I18nText id="features.platform.search" className="platform-features__search-tab" /> ), content: <Search />, }, { tabNum: 2, title: ( <I18nText id="features.platform.booking" className="platform-features__booking-tab" /> ), content: <Booking />, }, ]; const getItems = () => { return features.map(({ title, content }, index) => ({ key: index, title, content, })); }; const PlatformFeatures = () => { // Initialize selected tab based on URL hash (fallback to tab 0 if hash is invalid) const [selectedTabKey, setSelectedTabKey] = useState(() => { const hash = window.location.hash; if (hash.startsWith('#tab-')) { const tabId = parseInt(hash.replace('#tab-', ''), 10); return features.some(feature => feature.tabNum === tabId) ? tabId : 0; } return 0; // Default tab when no hash exists }); // Listen for hash changes to update the active tab useEffect(() => { const handleHashChange = () => { const hash = window.location.hash; if (hash.startsWith('#tab-')) { const tabId = parseInt(hash.replace('#tab-', ''), 10); if (features.some(feature => feature.tabNum === tabId)) { setSelectedTabKey(tabId); } } }; window.addEventListener('hashchange', handleHashChange); // Clean up the event listener on component unmount return () => window.removeEventListener('hashchange', handleHashChange); }, []); return ( <div className="platform-features__tabs"> <RTabs isVertical={true} items={getItems()} selectedTabKey={selectedTabKey} /> </div> ); }; export default PlatformFeatures;
Step 3: Fix HomePage Prop Type Errors
Your original HomePage had syntax issues in prop types—here's the corrected version:
import React from 'react'; import PropTypes from 'prop-types'; import Platform from './Platform'; const HomePage = ({ additionalProps }) => { const { routes } = additionalProps; return ( <div className="homepage"> <Platform routes={routes} /> </div> ); }; HomePage.defaultProps = { additionalProps: { routes: null, }, }; HomePage.propTypes = { additionalProps: PropTypes.shape({ routes: PropTypes.shape({ features: PropTypes.shape({ platform: PropTypes.string, }), }), }), }; export default HomePage;
How It All Works
- When a user clicks a link in
Platform, it opens a new tab with a URL like/platform-features#tab-1(usingtarget="_blank"andrel="noopener noreferrer"for security). - On initial load of
PlatformFeatures, the component parses the URL hash, validates it against existing tabs, and sets the active tab accordingly. - If the user edits the hash manually or follows a shared link, the
hashchangeevent listener will update the active tab automatically. - Invalid hashes will fall back to the default tab (we set it to 0 here, but you can adjust this to any valid tab index).
内容的提问来源于stack exchange,提问作者ashfaqrafi

