如何从Marvel API获取数据与图片?React路由及详情页开发问题
Hey there! Let's work through your two key problems: getting route-based comic detail pages working and correctly rendering Marvel's comic images. I'll use your existing code as a base to show exactly what to change.
1. Set Up Routing to Comic Detail Pages
First, we need to add routing to your app and make comic thumbnails clickable links.
Step 1: Install React Router
If you haven't already, install react-router-dom:
npm install react-router-dom # or yarn add react-router-dom
Step 2: Configure Routes in Your Root Component
Update your root component (like App.js) to define routes for the home page and comic detail page:
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import Home from './components/Home'; import ComicInfo from './components/ComicInfo'; function App() { return ( <Router> <Routes> <Route path="/" element={<Home />} /> <Route path="/comic/:comicId" element={<ComicInfo />} /> </Routes> </Router> ); } export default App;
Step 3: Make Comic Thumbnails Clickable (Update Home Component)
Wrap your ComicThumb in a Link component to navigate to the detail page. We'll also simplify the image URL construction by building it directly in the map:
// Add this import at the top of Home.js import { Link } from 'react-router-dom'; // ... keep your existing state and componentDidMount code ... render() { const { comics } = this.state; return ( <> <Header /> <Searchbar /> <ThreeColGrid> {comics.map((comic) => { // Build image URL directly for each comic const comicImage = `${comic.thumbnail.path}/${BACKDROP_SIZE}.${comic.thumbnail.extension}`; return ( <Link key={comic.id} to={`/comic/${comic.id}`}> <ComicThumb clickable={true} image={comicImage} comicId={comic.id} /> </Link> ); })} </ThreeColGrid> </> ); }
Step 4: Fetch & Display Comic Details (Update ComicInfo Component)
Use React hooks to grab the comic ID from the URL, fetch detail data from the Marvel API, and render the content properly:
import React, { useState, useEffect } from 'react'; import { useParams } from 'react-router-dom'; import ComicThumb from '../ComicThumb'; import { POSTER_SIZE, API_URL, API_KEY, HASH } from '../helpers'; const ComicInfo = () => { const [comic, setComic] = useState(null); const [loading, setLoading] = useState(true); const { comicId } = useParams(); useEffect(() => { const fetchComicDetails = async () => { try { const endpoint = `${API_URL}public/comics/${comicId}?ts=1&apikey=${API_KEY}&hash=${HASH}`; const result = await fetch(endpoint); const data = await result.json(); setComic(data.data.results[0]); } catch (error) { console.error('Error fetching comic details:', error); } finally { setLoading(false); } }; fetchComicDetails(); }, [comicId]); if (loading) return <div>Loading comic details...</div>; if (!comic) return <div>Comic not found!</div>; // Build valid image URL per Marvel's rules const comicImage = `${comic.thumbnail.path}/${POSTER_SIZE}.${comic.thumbnail.extension}`; return ( <div style={{ padding: '2rem' }}> <div style={{ display: 'flex', gap: '2rem', flexWrap: 'wrap' }}> <div> <ComicThumb image={comicImage} /> </div> <div> <h1>{comic.title}</h1> <h3>Description:</h3> <p>{comic.description || 'No description available.'}</p> <p><strong>Page Count:</strong> {comic.pageCount}</p> <p><strong>On Sale Date:</strong> {comic.dates.find(d => d.type === 'onsaleDate')?.date.slice(0, 10)}</p> </div> </div> </div> ); }; export default ComicInfo;
2. Correctly Build Marvel Image URLs
Marvel's image system uses a consistent structure: [thumbnail.path]/[size].[thumbnail.extension]. Valid size modifiers include:
- Portrait:
portrait_small,portrait_medium,portrait_xlarge - Landscape:
landscape_small,landscape_medium,landscape_incredible - Standard:
standard_small,standard_medium,standard_large
Ensure your helpers.js uses valid values, for example:
export const BACKDROP_SIZE = 'landscape_incredible'; export const POSTER_SIZE = 'portrait_xlarge';
Invalid size strings will result in broken images, so stick to Marvel's documented options!
Quick Tips
- Use the comic's
idas the map key (instead of index) for better React performance. - Add error handling for API calls (like the try/catch in
ComicInfo) to handle failed requests gracefully. - Double-check your
ComicThumbcomponent renders an<img>tag with thesrcprop set to the passed image URL.
内容的提问来源于stack exchange,提问作者Hervé




