React从Express后端取数:TopBar函数式组件数据获取疑问
Question Context:
I'm currently learning ReactJS paired with an ExpressJS backend. I've successfully implemented data fetching from the Express backend when the page loads using the componentWillMount() method in my class-based App.js component, and the code works perfectly:
// APP.JS componentWillMount() { fetch('/hotels') .then(res => res.json()) .then((result) => { this.getHotels(result); }); }
Now I've created a functional component TopBar for rendering a navigation header (similar to Stack Overflow or Facebook's navbar), with a code snippet like this:
// topbar.js const topBar = () => { return( <div className="top-bar"> {/* Navigation content here */} </div> ); }
How can I implement the same backend data fetching functionality in this functional TopBar component?
Since you're working with a functional component, class-based lifecycle methods like componentWillMount don't apply here. Instead, we'll use React's Hooks—specifically useState (to store fetched data) and useEffect (to handle side effects like API requests)—to replicate the data-fetching logic.
Step-by-Step Implementation:
- Import the required Hooks from React
- Declare a state variable to hold the data retrieved from your backend
- Use
useEffectto trigger the API request when the component mounts - Handle the API response and update your component's state
Complete TopBar Component Example:
// topbar.js import React, { useState, useEffect } from 'react'; const TopBar = () => { // Initialize state to store backend data (empty array as default) const [hotels, setHotels] = useState([]); // useEffect with empty dependency array runs once on component mount (matches componentWillMount timing) useEffect(() => { // Wrap fetch in an async function for cleaner async/await syntax const fetchHotels = async () => { try { const response = await fetch('/hotels'); const fetchedHotels = await response.json(); setHotels(fetchedHotels); // Update state with the fetched data // If you need to process the data (like your getHotels method), do it here: // processHotelData(fetchedHotels); } catch (error) { console.error('Failed to fetch hotels:', error); // Add error handling here (e.g., show a user-friendly message) } }; fetchHotels(); }, []); // Empty array ensures this runs only once on mount // Use the hotels state in your navigation bar rendering return ( <div className="top-bar"> {/* Example: Display number of hotels in the navbar */} <span className="hotel-count">Hotels: {hotels.length}</span> {/* Your existing navigation elements go here */} </div> ); }; export default TopBar;
Key Notes:
useEffectwith empty dependency array: This mimics the "run once on component mount" behavior of your originalcomponentWillMount(note thatcomponentWillMountis actually deprecated in React—for class components,componentDidMountis the recommended replacement).- Async/Await vs
.then(): I usedasync/awaithere for readability, but you could also stick with the.then()chain from your class component if you prefer—the functionality is identical. - Error Handling: The
try/catchblock prevents unhandled errors from crashing your app and lets you add user-facing error feedback if needed. - State Updates: When
setHotelsis called, React re-renders theTopBarcomponent with the new data, just likethis.setStatedoes in class components.
内容的提问来源于stack exchange,提问作者Khizar Amin

