React路由异常:所有页面被错误重定向至/product/:id页面
React路由重定向异常问题
- 现象:访问任意URL(包括
http://localhost:3000/)都会错误跳转到http://localhost:3000/product/<productID>;访问http://localhost:3000/products/women本应展示women分类商品列表,实际跳转到错误路径。 - 排查指向:
components/Product.jsx中的Navigate组件为问题根源。
App.jsx(路由配置)
import React from 'react' import Cart from './pages/Cart' import Home from './pages/Home' import Login from './pages/Login' import Product from './pages/Product' import ProductList from './pages/ProductList' import Register from './pages/Register' import { BrowserRouter as Router, Navigate, Route, Routes } from "react-router-dom"; const App = () => { const user = true; return ( <Router> <Routes> <Route exact path="/" element={<Home />} /> <Route exact path="/products/:category" element={<ProductList />} /> <Route exact path="/product/:id" element={<Product />} /> <Route exact path="/cart" element={<Cart />} /> <Route exact path="/register" element={user ? <Navigate to="/" /> : <Register />} /> <Route exact path="/login" element={user ? <Navigate to="/" /> : <Login />} /> </Routes> </Router> ) } export default App
Product.jsx(商品列表组件)
import React from 'react' import { useEffect, useState } from 'react'; import Product from './Product'; import axios from "axios" const Products = ({ cate, filters, sort }) => { console.log(cate, filters, sort) const [products, setProducts] = useState([]); const [filteredProducts, setFilteredProducts] = useState([]); useEffect(() => { const getProducts = () => { const res = axios.get( cate ? `http://localhost:8000/api/products?category=${cate}` : "http://localhost:8000/api/products") .then( function (res) { setProducts(res.data); console.log(res) } ).catch( function (err) { console.log(err) }); } getProducts(); }, [cate]); useEffect(() => { cate && setFilteredProducts( products.filter((item) => ( Object.entries(filters).every(([key, value]) => { return item[key].includes(value); } ) )) ) }, [products, cate, filters]) useEffect(() => { if ((sort === "newest")) { setFilteredProducts((prev) => [...prev].sort((a, b) => a.createdAt.localeCompare(b.createdAt)) ) } else if (sort === "asc") { setFilteredProducts((prev) => [...prev].sort((a, b) => a.price - b.price) ) } else { setFilteredProducts((prev) => [...prev].sort((a, b) => b.price - a.price) ) } },[sort]) return ( <Container > {cate ? filteredProducts.map((item) => ( <Product item={item} key={item._id} />)) : products.slice(0, 8).map((item) => <Product item={item} key={item._id} />)} </Container> ); };
pages/Product.jsx(商品详情页)
import { useLocation } from 'react-router-dom' import { useState, useEffect } from 'react'; import { publicRequest } from './requestMethods'; const Product = () => { // 返回路径 const location = useLocation(); const id = location.pathname.split("/")[2]; const [product, setProduct] = useState({}); useEffect(() => { const getProduct = async () => { try { const res = await publicRequest.get("/product/find/" + id); setProduct(res.data); } catch { } } getProduct(); }, [id])
ProductList.jsx(商品列表页)
import React from 'react' import { mobile } from './../responsive' import { useLocation } from 'react-router-dom'; import { useState } from 'react'; const ProductList = () => { // 返回路径 const location = useLocation(); const cate = location.pathname.split("/")[2]; console.log(location); // 设置selector的值,并返回 const [filters, setFilters] = useState({}); const [sort, setSort] = useState("newest"); const handleFilters = (e) => { const value = e.target.value; setFilters({ ...filters, [e.target.name]: value, }); }; console.log(filters) return ( <Container> <Navbar /> <Announcement /> <Title>Dresses</Title> <FilterContainer> <Filter><FilterText>Filter Products:</FilterText> <Select name="color" onChange={handleFilters}> <Option disabled>Color</Option> <Option>black</Option> <Option>white</Option> <Option>green</Option> <Option>wheat</Option> <Option>black</Option> <Option>red</Option> <Option>blue</Option> </Select> <Select name="size" onChange={handleFilters}> <Option disabled>Size</Option> <Option>XS</Option> <Option>S</Option> <Option>M</Option> <Option>L</Option> <Option>XL</Option> </Select></Filter> <Filter><FilterText>Sort Products: <Select onChange={(e) => setSort(e.target.value)}> <Option value="newest">Newest</Option> <Option value="asc">Price(asc)</Option> <Option value="desc">Price(desc)</Option> </Select></FilterText></Filter> </FilterContainer> <Products cate={cate} filters={filters} sort={sort} /> <NewsLetter /> <Footer /> </Container> ) }
components/Product.jsx(商品卡片组件)
const Product = ({ item }) => { return ( <Container className='container product'> <Circle /> <Img src={item.img} /> <Info > <Icon > <ShoppingCartOutlinedIcon /> </Icon> <Icon> <Navigate to={`/product/${item._id}`}> <SearchOutlinedIcon /> </Navigate> </Icon> <Icon> <FavoriteBorderOutlinedIcon /> </Icon> </Info> </Container> ) }
问题根源与修复方案
问题出在components/Product.jsx的Navigate组件使用方式错误:React Router v6中,Navigate是渲染时立即触发重定向的组件,并非用于包裹点击元素的导航容器。当前写法会导致组件一渲染就执行重定向,而非点击图标时才跳转。
修复方式1:使用Link组件(推荐的声明式导航)
import { Link } from 'react-router-dom'; // 导入其他必要组件(如Icon、SearchOutlinedIcon等) const Product = ({ item }) => { return ( <Container className='container product'> <Circle /> <Img src={item.img} /> <Info > <Icon > <ShoppingCartOutlinedIcon /> </Icon> <Icon> <Link to={`/product/${item._id}`}> <SearchOutlinedIcon /> </Link> </Icon> <Icon> <FavoriteBorderOutlinedIcon /> </Icon> </Info> </Container> ) }
修复方式2:使用useNavigate钩子(命令式导航)
import { useNavigate } from 'react-router-dom'; // 导入其他必要组件 const Product = ({ item }) => { const navigate = useNavigate(); const handleGoToProduct = () => { navigate(`/product/${item._id}`); }; return ( <Container className='container product'> <Circle /> <Img src={item.img} /> <Info > <Icon > <ShoppingCartOutlinedIcon /> </Icon> <Icon onClick={handleGoToProduct}> <SearchOutlinedIcon /> </Icon> <Icon> <FavoriteBorderOutlinedIcon /> </Icon> </Info> </Container> ) }
内容的提问来源于stack exchange,提问作者Anna
相关产品推荐
相关产品推荐

