ReactJS中如何向事件处理器传递常量至StationOne组件
Hey there! Let's break down how to solve this problem while fixing a few React anti-patterns in your current code. First, let's address the main issues in your existing approach, then walk through the corrected solution.
Key Issues in Your Current Code
- Direct DOM manipulation: Using
getElementByIdandinnerHTMLgoes against React's data-driven approach—we should use state to manage and render data instead. - Incorrect onClick usage: You're passing the
StationOnecomponent directly toonClick, which won't trigger the component properly. Instead, we need to pass data to the component via routing when the link is clicked. - Potential array index out-of-bounds: Your API call uses
limit=2, sodata.stationswill only have 2 items (indexes 0 and 1)—accessingdata.stations[2]will throw an error. - Variable name mismatches: You reference elements like
nameStationEinsbut your HTML usesnameStationOne(and vice versa), which will cause DOM queries to fail.
Step-by-Step Solution
1. Use React State to Manage Data
First, let's replace DOM manipulation with React useState hooks to track your location and nearby stations. This keeps your data in sync with the UI automatically.
2. Pass Station Data via React Router
Instead of trying to trigger the component directly in onClick, we'll use React Router's Link component to pass station data to the StationOne component via route state. Then, StationOne can retrieve this data and make its fetch request.
Corrected HomePage Component
import React, { useState, useEffect } from 'react'; import { Link } from 'react-router-dom'; const HomePage = () => { const [currentLocation, setCurrentLocation] = useState(''); const [nearbyStations, setNearbyStations] = useState([]); // Use useEffect to run geolocation on component mount useEffect(() => { const geoSuccess = (loca) => { const lat = loca.coords.latitude; const long = loca.coords.longitude; const url = `http://transport.opendata.ch/v1/locations?limit=3&x=${lat}&y=${long}`; // Increase limit to 3 for 2 nearby stations fetch(url) .then((resp) => resp.json()) .then((data) => { // Update state with location and nearby stations setCurrentLocation(data.stations[0].name); // Grab the next 2 stations (indexes 1 and 2) if they exist setNearbyStations(data.stations.slice(1, 3)); }) .catch((err) => console.log('Fetch error:', err)); }; const geoError = (error) => { console.log('Geolocation error:', error); }; window.navigator.geolocation.getCurrentPosition(geoSuccess, geoError); }, []); // Empty dependency array runs once on mount return ( <div> <h1>Your Location:</h1> <h3>{currentLocation || 'Loading...'}</h3> <h2>Stations near your location:</h2> {nearbyStations.length > 0 ? ( <> <Link to={{ pathname: '/first-connection', state: { stationName: nearbyStations[0].name } }} > <h3>{nearbyStations[0].name}</h3> </Link> <Link to={{ pathname: '/second-connection', state: { stationName: nearbyStations[1]?.name } }} > <h3>{nearbyStations[1]?.name || 'No second station found'}</h3> </Link> </> ) : ( <p>Loading nearby stations...</p> )} </div> ); }; export default HomePage;
Corrected StationOne Component
Now, in StationOne, we'll use React Router's useLocation hook to retrieve the passed station name and make the fetch request:
import React, { useState, useEffect } from 'react'; import { useLocation } from 'react-router-dom'; const StationOne = () => { const location = useLocation(); const [departures, setDepartures] = useState([]); const stationName = location.state?.stationName; useEffect(() => { if (!stationName) return; // Fetch departures using the passed station name const url = `http://transport.opendata.ch/v1/stationboard?station=${encodeURIComponent(stationName)}`; fetch(url) .then((resp) => resp.json()) .then((data) => { setDepartures(data.stationboard); }) .catch((err) => console.log('Departure fetch error:', err)); }, [stationName]); return ( <div> <h1>Departures from {stationName}</h1> {departures.length > 0 ? ( <ul> {departures.map((departure, index) => ( <li key={index}> {departure.name} - {departure.to} at {new Date(departure.stop.departure).toLocaleTimeString()} </li> ))} </ul> ) : ( <p>Loading departures...</p> )} </div> ); }; export default StationOne;
Key Explanations
- State Management: We use
useStateto store location and station data, so React automatically re-renders the UI when data changes—no need for manual DOM updates. - Route State: The
Linkcomponent'stoprop accepts an object with astatefield, which lets us pass arbitrary data to the target route. - useLocation Hook: In
StationOne,useLocationgives us access to the route state, so we can get the station name and use it in our fetch request. - Error Handling: We added optional chaining (
?.) to avoid errors if a second station doesn't exist, and wrapped fetch calls incatchblocks to log errors.
内容的提问来源于stack exchange,提问作者Luciano M.

