React中关联facilities与activities数据集并实现设施选择后展示对应活动时间表的解决方案咨询
Let's break down your problem and fix things step by step. First, let's spot the key issues in your current code, then implement the correct approach to link facilities with their activities.
1. Fix the Route Configuration
First, your App.js needs to define a dynamic route parameter to capture the selected facility's ID. Update your route setup like this:
function App() { return ( <Router> <div> <Routes> <Route exact path="/" element={<Home />} /> {/* Add dynamic facilityId parameter to the route */} <Route path="/activities/:facilityId" element={<Activities />} /> </Routes> </div> </Router> ); }
2. Correct the Link in Facilities.js
Your current Link path is incorrect—you don't need the : in the actual URL (that's only for route definitions). Instead, pass the selected facility's ID directly. Also, use the facility's unique ID as the component key for consistency:
import { useMemo } from 'react'; const Facilities = ({ facilitiesResult }) => { // Cache cloned activities data to avoid redundant work on every render const activitiesData = useMemo(() => structuredClone(activities.data), []); return( <Container> {facilitiesResult .slice(0, 6) .sort((a, b) => a.name.localeCompare(b.name)) .map((facility) => ( <FacilitiesCard key={facility.id}> <Heading>{facility.name.replaceAll('_', ' ')}</Heading> {/* Link to the correct URL with the facility's ID */} <Link to={`/activities/${facility.id}`}> <p>View</p> </Link> </FacilitiesCard> ))} </Container> ) }
3. Fetch and Display Relevant Data in Activities.js
Here's where you'll connect the dots using React Router's useParams hook to get the selected facility ID, then filter your data to show only matching activities and facility details:
import { useParams } from 'react-router-dom'; import { useMemo } from 'react'; const Activities = () => { const { facilityId } = useParams(); // Convert URL param to number (params are always strings by default) const selectedFacilityId = Number(facilityId); // Memoize filtered data to avoid recalculating on every render const selectedFacility = useMemo(() => { return facilities.data.find(facility => facility.id === selectedFacilityId); }, [selectedFacilityId]); const facilityActivities = useMemo(() => { return activities.data.filter(activity => activity.facility_id === selectedFacilityId); }, [selectedFacilityId]); // Handle case where the facility doesn't exist if (!selectedFacility) { return <div>Facility not found</div>; } return( <div style={{ padding: '2rem' }}> <h1>{selectedFacility.name} - Daily Activities</h1> <h3>Facility Tags: {selectedFacility.tags.map(tag => tag.name).join(', ')}</h3> {facilityActivities.length === 0 ? ( <p>No activities scheduled for this facility today.</p> ) : ( facilityActivities.map((activity) => ( <div key={activity.id} style={{ margin: '1rem 0', padding: '1rem', border: '1px solid #eee', borderRadius: '4px' }}> <h3>{activity.name}</h3> <p><strong>Time:</strong> {activity.start_time} - {activity.end_time}</p> <p><strong>Level:</strong> {activity.level}</p> <p><strong>Location:</strong> {activity.location}</p> <p><strong>Tags:</strong> {activity.tags.map(tag => tag.name).join(', ')}</p> </div> )) )} </div> ) };
4. Do You Need to Merge Datasets?
You mentioned trying to merge datasets earlier—this isn't necessary for your use case. Merging would create a single array of facilities with embedded activities, but since you're navigating to a separate page for each facility, filtering on the fly using the route parameter is more flexible and easier to maintain.
If you ever need to display all facilities with their activities on one page, creating a map of facility IDs to their activities could make sense (e.g., const facilityActivitiesMap = new Map(facilities.data.map(f => [f.id, []])) then populating it with activities), but for this specific flow, filtering per route is optimal.
Key Takeaways
- Use React Router's
useParamsto capture dynamic URL parameters - Always convert URL params to the correct type (string → number) since params are always strings
- Use
useMemoto cache filtered/computed data and avoid unnecessary re-renders - Link URLs should use actual values (not route parameter syntax like
:facilityId)
内容的提问来源于stack exchange,提问作者RomanV

