React表情包生成器API路由不匹配及编辑页图片不显示问题
React表情包生成器路由匹配错误与图片不显示修复方案
问题根源
- 路由规则不匹配:App中定义的是动态URL参数路由
/edit/:url,但Card组件跳转时使用的是查询参数格式/edit?url=xxx,导致路由无法匹配,触发"No routes matched location"错误。 - 参数获取逻辑错误:EditPage组件中误用
useParams()的get()方法(这是查询参数的用法),且因路由未匹配成功,无法获取到图片URL,导致图片无法渲染。
修复方案(推荐使用查询参数方式)
1. 修正App.jsx的路由配置
将编辑页路由改为无参数的路径,因为查询参数不需要在路由规则中定义:
// App.jsx import React from "react"; import { Routes, Route } from "react-router-dom"; import "bootstrap/dist/css/bootstrap.min.css"; import Homepage from "./pages/Home"; import EditPage from "./pages/Edit"; import './App.css'; function App() { return ( <> <div className="container"> <h1>App Meme Generator</h1> <Routes> <Route path="/" element={<Homepage/>}/> <Route path="/edit" element={<EditPage/>}/> {/* 移除:url */} </Routes> </div> </> ) }; export default App;
2. 优化Card.jsx的跳转逻辑
对图片URL进行编码,避免特殊字符导致的路由解析问题:
// Card.jsx import React from 'react'; import { useNavigate } from 'react-router-dom'; import Button from 'react-bootstrap/Button'; import Card from 'react-bootstrap/Card'; const CardMeme = (props) => { const navigate = useNavigate(); return ( <Card style={{ width: '18rem', margin: '25px' }}> <Card.Img variant="top" src={props.img} /> <Card.Body> <Card.Title>{props.title}</Card.Title> {/* 对URL编码后传递 */} <Button onClick={e => navigate(`/edit?url=${encodeURIComponent(props.img)}`)} variant="primary">Edit</Button> </Card.Body> </Card> ) } export default CardMeme;
3. 修正EditPage.jsx的参数获取逻辑
使用useSearchParams()获取查询参数,并解码图片URL:
// Edit.jsx import React, { useState, createRef } from "react"; import Text from "../components/Text"; import { Button } from "bootstrap"; import { useNavigate, useSearchParams } from "react-router-dom"; // 替换useParams为useSearchParams import { exportComponentAsJPEG } from "react-component-export-image"; const EditPage = () => { const [searchParams] = useSearchParams(); const [count, setCount] = useState(0); const memeUrl = decodeURIComponent(searchParams.get("url")); // 解码获取图片URL const memeRef = createRef(); const addText = () => { setCount(count + 1); }; return ( <div> <div style={{ width: "700px" }} ref={memeRef} className="meme mt-5 mb-5"> <img src={memeUrl} width="250px" /> {/* 使用解码后的URL */} {Array(count) .fill(0) .map((_, index) => ( <Text key={index} /> ))} </div> <Button onClick={addText}>Añadir Texto</Button> <Button variant="success" onClick={(e) => exportComponentAsJPEG(memeRef)}> Save </Button> </div> ); }; export default EditPage;
4. 简化Home.jsx代码
Home组件中定义的handleEditClick并未被Card组件使用,可删除冗余代码:
// Home.jsx import React, { useEffect, useState } from "react"; import CardMeme from "../components/Card"; import { getAllMemes } from "../api/memes"; const Homepage = () => { const [data, setData] = useState([]); useEffect(() => { getAllMemes().then((meme) => setData(meme.data.memes)); }, []); return ( <div className="row"> {data.map((el) => ( <CardMeme key={el.id} img={el.url} title={el.name} /> ))} </div> ); }; export default Homepage;
可选方案(使用动态URL参数)
若偏好使用动态URL参数,可按以下步骤修改:
- 保持App.jsx的路由
/edit/:url不变 - 修改Card.jsx的跳转逻辑:
<Button onClick={e => navigate(`/edit/${encodeURIComponent(props.img)}`)} variant="primary">Edit</Button>
- 修改EditPage.jsx的参数获取:
import { useNavigate, useParams } from "react-router-dom"; const EditPage = () => { const params = useParams(); const memeUrl = decodeURIComponent(params.url); // ...其余代码不变 }
内容的提问来源于stack exchange,提问作者HarryBerger
相关产品推荐
相关产品推荐

