使用react路由器dom v 6。我没有合适的单词来表达这个问题,但问题是addToCart处理程序的url在app.js中找不到addToCarts路径。例如,当我单击id为2的产品时,我会在控制台No routes matched location "/cart/2?qty=1"
中显示此错误。这同样适用于所选的任何其他产品。
function ProductScreen({}) {
const [qty, setQty] = useState(1)
const history = useNavigate()
const match = useParams();
const dispatch = useDispatch()
const productDetails = useSelector(state => state.productDetails)
const {error, loading, product} = productDetails
useEffect(() => {
dispatch(listProductDetails(match.id))
}, [dispatch, match])
const addToCartHandler = () =>{
history(`/cart/${match.id}?qty=${qty}`)
}
return(
<Button onClick={addToCartHandler} Add To Cart </Button>
)
}
CartScreen
const CartScreen = () => {
const { id } = useParams();
const { search } = useLocation();
const [searchParms] = useSearchParams();
const productId = id;
const qty = search ? Number(search.split("=")[1]) : 1;
const dispatch = useDispatch()
useEffect(() => {
if (productId){
dispatch(addToCart(productId, qty))
}
}, [dispatch, productId, qty])
return (
<div>
<h1>Add to CART</h1>
</div>
);
};
export default CartScreen
App.js
function App() {
return (
<Router>
<Routes>
<Route path='/product/:id' element={<ProductScreen/>} />
<Route path='/cart/:id' element={<CartScreen/>} />
<Route path='/cart/' element={<CartScreen/>} />
</Routes>
</Router>
);
}
将<Route path='/cart/:id' element={<CartScreen/>} />
更改为<Route path='/cart/:id?' element={<CartScreen/>} />
并不能解决此问题。请注意,我测试的这两个路由的差异是第二个路由的路径中的?
。
假设您的代码片段被复制/粘贴到一个正在运行的代码沙盒中,但相同的代码在本地不起作用,并且您仍然看到一个不变的错误No routes matched location "/cart/2?qty=1"
,我建议您完全重新启动。路径"/cart/2"
当然应该匹配。
我通常采取的调试/故障排除步骤:
- 杀死所有正在运行的代码观察程序/热重载程序,并完全清除浏览器缓存,然后重新启动开发构建(
npm start
( - 完全关闭/重新打开浏览器,然后运行重新生成
- 试着在隐姓埋名的窗口中运行它们
- 重新启动运行代码的机器
常量数量=搜索?数字(search.split("="([1](:1;
更换这个
让qty=location.search?数字(search.split("="([1](:1;
然后是id为的productID
以下是我所做的:
使用useNavigate In product screen
const navigate = useNavigate()
然后处理器
const addToCartHandler = () => {
navigate(`/cart/${id}?qty=${qty}`)
}
在app.js文件中,将路由添加为:
<Route path='/cart/:id?' element={<CartScreen />} />
这应该有助于
import { useNavigate, useParams } from "react-router-dom";
import React, { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Link } from "react-router-dom";
import {
Row,
Col,
Image,
ListGroup,
Card,
Button,
ListGroupItem,
Form,
} from "react-bootstrap";
import Rating from "../components/Rating";
import { listProductDetails } from "../actions/productActions";
// import products from "../products";
// console.log(products)
const ProductScreen = ({ match }) => {
const [qty, setQty] = useState(0);
const navigate = useNavigate();
const dispatch = useDispatch();
const { id } = useParams();
useEffect(() => {
dispatch(listProductDetails(id));
}, [dispatch, id]);
const addToCartHandler = () => {
navigate(`/cart/${id}?qty=${qty}`);
}
const productDetails = useSelector((state) => state.productDetails);
const { loading, product } = productDetails;
// console.log(loading, product);
return (
<>
{loading === false ? (
<div>
<Link className="btn btn-dark my-3" to="/">
Go Back
</Link>
<Row>
<Col md={6}>
<Image src={product.image} alt={product.name} fluid></Image>
</Col>
<Col md={3}>
<ListGroup variant="flush">
<ListGroup.Item>
<h3>{product.name}</h3>
</ListGroup.Item>
<ListGroupItem>
<Rating
value={product.rating}
text={`${product.numReviews} reviews`}
/>
</ListGroupItem>
<ListGroupItem>Price:${product.price}</ListGroupItem>
<ListGroupItem>Description:{product.description}</ListGroupItem>
</ListGroup>
</Col>
<Col md={3}>
<Card>
<ListGroup variant="flush">
<ListGroupItem>
<Row>
<Col>Price</Col>
<Col>
<strong>${product.price}</strong>
</Col>
</Row>
</ListGroupItem>
<ListGroupItem>
<Row>
<Col>Status:</Col>
<Col>
{product.countInStock > 0 ? `In Stock` : `Out of Stock`}
</Col>
</Row>
</ListGroupItem>
{product.countInStock > 0 && (
<ListGroupItem>
<Row>
<Col>Qty</Col>
<Col>
<Form.Control
as="select"
value={qty}
onChange={(e) => setQty(e.target.value)}
>
{[...Array(product.countInStock).keys()].map(
(x) => (
<option key={x + 1} value={x + 1}>
{x + 1}
</option>
)
)}
</Form.Control>
</Col>
</Row>
</ListGroupItem>
)}
<ListGroupItem>
<Button
onClick={addToCartHandler}
className="btn-block "
type="button"
disabled={product.countInStock === 0}
>
ADD To Cart
</Button>
</ListGroupItem>
</ListGroup>
</Card>
</Col>
</Row>
</div>
) : (
<p>Please wait....</p>
)}
</>
);
};
export default ProductScreen;