如何在React onClick事件中传递ID并避免页面重载?
问题解决:点击博客卡片页面重载导致请求中断的方案
问题诊断
页面重载说明React Router的客户端路由跳转未生效,触发了浏览器硬导航,进而中断了axios请求。核心原因通常是useNavigate未在Router上下文内工作、路由路径错误,或是存在默认浏览器行为干扰。
具体解决方案
1. 确保组件在Router上下文内
useNavigate必须被BrowserRouter(或其他Router组件)包裹才能正常生效,否则调用navigate会失效并触发页面刷新。检查根组件配置:
import { BrowserRouter } from 'react-router-dom'; function App() { return ( <BrowserRouter> {/* 包含BlogCard的所有路由组件需在此范围内 */} </BrowserRouter> ); }
2. 修正路由路径与数据传递
- 使用绝对路径避免路由解析错误
- 传递axios响应的
data属性(而非整个响应对象),避免序列化问题
const singleBlogHandler = async id => { const singleBlogDetail = await axios.get( `https://61791a83aa7f3400174047a6.mockapi.io/v1/GetBLogs/${id}` ); // 改为绝对路径,传递真实数据 navigate(`/blogs/${id}`, { state: singleBlogDetail.data }); };
3. 阻止默认事件(若存在)
如果Stack内部包含<a>、<button>等元素,点击时可能触发浏览器默认行为,需手动阻止:
const singleBlogHandler = async (id, e) => { e.preventDefault(); // 阻止默认跳转/提交行为 const singleBlogDetail = await axios.get( `https://61791a83aa7f3400174047a6.mockapi.io/v1/GetBLogs/${id}` ); navigate(`/blogs/${id}`, { state: singleBlogDetail.data }); }; // 调用时传递事件对象 <Stack key={blog.id} onClick={(e) => singleBlogHandler(blog.id, e)} > {/* 博客内容 */} </Stack>
优化建议:跳转后再请求数据(推荐)
当前先请求再跳转的逻辑易受页面刷新影响,改为跳转至详情页后再请求数据,更符合单页应用最佳实践:
BlogCard组件修改
const BlogCard = ({ blogs }) => { const navigate = useNavigate(); const singleBlogHandler = (id) => { // 仅传递ID,详情页自行请求数据 navigate(`/blogs/${id}`); }; return ( <> {blogs.map(blog => ( <Stack key={blog.id} onClick={() => singleBlogHandler(blog.id)} > {/* 博客内容 */} </Stack> ))} </> ); };
详情页组件(示例)
import { useEffect, useState } from 'react'; import axios from 'axios'; import { useParams } from 'react-router-dom'; const BlogDetail = () => { const { id } = useParams(); const [blog, setBlog] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { const fetchBlog = async () => { try { const res = await axios.get( `https://61791a83aa7f3400174047a6.mockapi.io/v1/GetBLogs/${id}` ); setBlog(res.data); } catch (err) { console.error('获取博客失败:', err); } finally { setLoading(false); } }; fetchBlog(); }, [id]); if (loading) return <div>加载中...</div>; if (!blog) return <div>博客不存在</div>; return ( <div> <h1>{blog.title}</h1> <p>{blog.content}</p> </div> ); }; export default BlogDetail;
内容的提问来源于stack exchange,提问作者Sohaib Ashraf
相关产品推荐
相关产品推荐

