React组件中async/await函数使用问题:调用后返回Promise而非目标数组的解决方法
Got it, let's break this down for you! The reason console.log(Data) shows a Promise instead of your array is that every async function returns a Promise by default—it doesn't spit out the final value right away, even if you use await inside it.
Since you're working in a React component and want to avoid messy .then() chains, here's the clean, React-friendly way to handle this:
1. Use React state to store your data
First, you'll need a state variable to hold the fetched array once it's ready. Import useState and useEffect from React if you haven't already:
import { useState, useEffect } from 'react'; function YourComponent() { // Initialize state with an empty array const [characters, setCharacters] = useState([]); // Add loading state to handle the waiting period (optional but recommended) const [isLoading, setIsLoading] = useState(true);
2. Use useEffect with an async inner function
You can't make the useEffect callback itself async (React doesn't allow it), but you can define an async function inside the effect and call it immediately:
useEffect(() => { const getCharacters = async () => { try { // Await the Promise returned by fetchData() to get the actual array const result = await fetchData(); // Update state with the fetched data, fallback to empty array if result is undefined setCharacters(result || []); } catch (error) { console.error('Failed to fetch data:', error); // Optionally set an error state here to show user feedback } finally { // Stop loading once the request finishes (success or failure) setIsLoading(false); } }; getCharacters(); }, []); // Empty dependency array = run only once when the component mounts
3. Render based on state
Now you can use your state to render content conditionally, so you don't try to render data that hasn't loaded yet:
if (isLoading) { return <div>Loading characters...</div>; } return ( <div> <h2>Better Call Saul Characters</h2> <ul> {characters.map(character => ( <li key={character.id}>{character.name}</li> ))} </ul> </div> ); }
Bonus: Using async in event handlers
If you need to call fetchData in response to a user action (like a button click), you can make the event handler itself async—no need for .then() here either:
const handleFetchClick = async () => { setIsLoading(true); const result = await fetchData(); setCharacters(result || []); setIsLoading(false); }; // Then use it in your JSX: <button onClick={handleFetchClick}>Refresh Characters</button>
A quick note on your fetchData function
Your current fetchData catches errors but doesn't re-throw them, which means if the request fails, it returns undefined. Adding a fallback (like result || [] when updating state) helps avoid unexpected behavior. If you want to handle errors explicitly in your component, you could modify fetchData to re-throw the error:
async function fetchData() { try { const resultRes = await fetch("https://www.breakingbadapi.com/api/characters?category=Better+Call+Saul"); if (!resultRes.ok) { throw new Error(`HTTP error! Status: ${resultRes.status}`); } const result = await resultRes.json(); return result; } catch (error) { console.error(error); throw error; // Re-throw so the component can handle it } }
内容的提问来源于stack exchange,提问作者MiSiMa49

