为什么 "useParams()" return "undefined"?需要反应路由器/可选参数/useParams 的帮助
Why does "useParams()" return "undefined"? Need help for react router/ optional parameter/ useParams
我是 react 和 react-router-dom 的新手。我需要你的帮助来学习如何从 react-router 获取参数。因此,我提前感谢您花时间解决我的问题。
我正在尝试使用 React 重新创建一个 SPA 店。您可以在 GitHub link.
找到我的代码
这些是我正在使用的依赖项:
"dependencies": {
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^12.1.4",
"@testing-library/user-event": "^13.5.0",
"axios": "^0.26.1",
"react": "^18.0.0",
"react-bootstrap": "^2.2.3",
"react-dom": "^18.0.0",
"react-redux": "^7.2.8",
"react-router-bootstrap": "^0.26.1",
"react-router-dom": "^6.3.0",
"react-scripts": "^2.1.3",
"redux": "^4.1.2",
"redux-devtools-extension": "^2.13.9",
"redux-thunk": "^2.4.1",
"web-vitals": "^2.1.4"
}
我想要的是通过添加对象的数量来创建一个购物车。通过使用 redux,我试图将我的用户重定向到购物车。起初,我想使用“history”和可选参数“?”,但是,我发现它们在 react v6 中不受支持,所以我使用了另一个名为“useNavigate”的钩子。我的productScreen.js中的代码如下:
import React, { useState, useEffect } from "react";
import { Link, useParams, useNavigate } from "react-router-dom";
import {
Row,
Col,
Image,
ListGroup,
Card,
Button,
Form,
} from "react-bootstrap";
import Rating from "../components/Rating";
import { useDispatch, useSelector } from "react-redux";
import { listProductDetails } from "../actions/productActions";
import Loader from "../components/Loader";
import Message from "../components/Message";
const ProductScreen = () => {
const [qty, setQty] = useState(1);
const { id } = useParams();
const dispatch = useDispatch();
const productDetails = useSelector((state) => state.productDetails);
const { loading, error, product } = productDetails;
useEffect(() => {
dispatch(listProductDetails(id));
}, [dispatch, id]);
const navigate = useNavigate();
const addToCartHandler = () => {
navigate(`/cart/${id}?qty=${qty}`);
};
return (
<>
<Link className="btn btn-dark my-3" to="/">
Go Back
</Link>
{loading ? (
<Loader />
) : error ? (
<Message variant="danger">{error}</Message>
) : (
<Row>
<Col ms={6}>
<Image src={product.image} alt={product.name} fluid />
</Col>
<Col md={3}>
<ListGroup variant="flush">
<ListGroup.Item>
<h3>{product.name}</h3>
</ListGroup.Item>
<ListGroup.Item>
<Rating
value={product.rating}
text={`${product.numReviews} reviews`}
/>
</ListGroup.Item>
<ListGroup.Item>Price: ${product.price};</ListGroup.Item>
<ListGroup.Item>
Description: ${product.description};
</ListGroup.Item>
</ListGroup>
</Col>
<Col md={3}>
<Card>
<ListGroup variant="flush">
<ListGroup.Item>
<Row>
<Col>Price</Col>
<Col>
<strong>{product.price}</strong>
</Col>
</Row>
</ListGroup.Item>
<ListGroup.Item>
<Row>
<Col>Status</Col>
<Col>
{product.countInStock > 0 ? "InStock" : "Out of Stock"}
</Col>
</Row>
</ListGroup.Item>
{product.countInStock > 0 && (
<ListGroup.Item>
<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>
</ListGroup.Item>
)}
<ListGroup.Item>
<Button
className="btn-block"
type="button"
disabled={product.countInStock === 0}
onClick={addToCartHandler}
>
Add To Cart
</Button>
</ListGroup.Item>
</ListGroup>
</Card>
</Col>
</Row>
)}
</>
);
};
export default ProductScreen;
我正在使用 navigate 将用户重定向到我的购物车,并绕过 id 参数和 qty 作为查询字符串来连接到本地存储和数据库。
由于 react router v6 不支持可选参数,我将我的路由器设计如下:
<Routes>
<Route path="/" element={<HomeScreen />} />
<Route path="/product/:id" element={<ProductScreen />} />
<Route path="/cart" element={<CartScreen />} />
<Route path="/cart/:id" element={<CartScreen />} />
</Routes>
在我的 cartScreen.js 文件中,我可以使用名为“research”的钩子获取查询。另一方面,当我尝试获取 id 参数时,“useParam”钩子 returns 未定义。
import React, { useEffect } from "react";
import {
Link,
useSearchParams,
useNavigate,
useParams,
} from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import Message from "../components/Message";
import {
Row,
Col,
ListGroup,
Image,
Form,
Button,
Card,
} from "react-bootstrap";
import { addToCart } from "../actions/cartActions";
import { disable } from "colors";
const CartScreen = () => {
const { productID } = useParams();
console.log(productID);
const [qtyString] = useSearchParams();
const qty = Number(qtyString.toString().split("=")[1]);
console.log(qty)
const dispatch = useDispatch();
useEffect(() => {
if (productID) {
dispatch(addToCart(productID, qty));
}
}, [dispatch, productID, qty]);
return <div>CartScreen</div>;
};
export default CartScreen;
你介意教我如何从路由器获取参数(“id”)吗?任何帮助,将不胜感激。
谢谢,
这里的参数叫做id
:<Route path="/cart/:id" element={<CartScreen />} />
您做对了产品:const { id } = useParams();
但在购物车中您将其命名为 productID
:
const { productID } = useParams();
console.log(productID);
改为:
const { id } = useParams();
console.log(id);
所以你的问题就在这条线上
const { productID } = useParams(); <=========
在这里你必须输入你在路由中定义的相同名称,在你的情况下是 :id
见下文
<Route path="/product/:id" element={<ProductScreen />} />
所以你需要做的是:
const { id } = useParams();
我是 react 和 react-router-dom 的新手。我需要你的帮助来学习如何从 react-router 获取参数。因此,我提前感谢您花时间解决我的问题。 我正在尝试使用 React 重新创建一个 SPA 店。您可以在 GitHub link.
找到我的代码这些是我正在使用的依赖项:
"dependencies": {
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^12.1.4",
"@testing-library/user-event": "^13.5.0",
"axios": "^0.26.1",
"react": "^18.0.0",
"react-bootstrap": "^2.2.3",
"react-dom": "^18.0.0",
"react-redux": "^7.2.8",
"react-router-bootstrap": "^0.26.1",
"react-router-dom": "^6.3.0",
"react-scripts": "^2.1.3",
"redux": "^4.1.2",
"redux-devtools-extension": "^2.13.9",
"redux-thunk": "^2.4.1",
"web-vitals": "^2.1.4"
}
我想要的是通过添加对象的数量来创建一个购物车。通过使用 redux,我试图将我的用户重定向到购物车。起初,我想使用“history”和可选参数“?”,但是,我发现它们在 react v6 中不受支持,所以我使用了另一个名为“useNavigate”的钩子。我的productScreen.js中的代码如下:
import React, { useState, useEffect } from "react";
import { Link, useParams, useNavigate } from "react-router-dom";
import {
Row,
Col,
Image,
ListGroup,
Card,
Button,
Form,
} from "react-bootstrap";
import Rating from "../components/Rating";
import { useDispatch, useSelector } from "react-redux";
import { listProductDetails } from "../actions/productActions";
import Loader from "../components/Loader";
import Message from "../components/Message";
const ProductScreen = () => {
const [qty, setQty] = useState(1);
const { id } = useParams();
const dispatch = useDispatch();
const productDetails = useSelector((state) => state.productDetails);
const { loading, error, product } = productDetails;
useEffect(() => {
dispatch(listProductDetails(id));
}, [dispatch, id]);
const navigate = useNavigate();
const addToCartHandler = () => {
navigate(`/cart/${id}?qty=${qty}`);
};
return (
<>
<Link className="btn btn-dark my-3" to="/">
Go Back
</Link>
{loading ? (
<Loader />
) : error ? (
<Message variant="danger">{error}</Message>
) : (
<Row>
<Col ms={6}>
<Image src={product.image} alt={product.name} fluid />
</Col>
<Col md={3}>
<ListGroup variant="flush">
<ListGroup.Item>
<h3>{product.name}</h3>
</ListGroup.Item>
<ListGroup.Item>
<Rating
value={product.rating}
text={`${product.numReviews} reviews`}
/>
</ListGroup.Item>
<ListGroup.Item>Price: ${product.price};</ListGroup.Item>
<ListGroup.Item>
Description: ${product.description};
</ListGroup.Item>
</ListGroup>
</Col>
<Col md={3}>
<Card>
<ListGroup variant="flush">
<ListGroup.Item>
<Row>
<Col>Price</Col>
<Col>
<strong>{product.price}</strong>
</Col>
</Row>
</ListGroup.Item>
<ListGroup.Item>
<Row>
<Col>Status</Col>
<Col>
{product.countInStock > 0 ? "InStock" : "Out of Stock"}
</Col>
</Row>
</ListGroup.Item>
{product.countInStock > 0 && (
<ListGroup.Item>
<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>
</ListGroup.Item>
)}
<ListGroup.Item>
<Button
className="btn-block"
type="button"
disabled={product.countInStock === 0}
onClick={addToCartHandler}
>
Add To Cart
</Button>
</ListGroup.Item>
</ListGroup>
</Card>
</Col>
</Row>
)}
</>
);
};
export default ProductScreen;
我正在使用 navigate 将用户重定向到我的购物车,并绕过 id 参数和 qty 作为查询字符串来连接到本地存储和数据库。
由于 react router v6 不支持可选参数,我将我的路由器设计如下:
<Routes>
<Route path="/" element={<HomeScreen />} />
<Route path="/product/:id" element={<ProductScreen />} />
<Route path="/cart" element={<CartScreen />} />
<Route path="/cart/:id" element={<CartScreen />} />
</Routes>
在我的 cartScreen.js 文件中,我可以使用名为“research”的钩子获取查询。另一方面,当我尝试获取 id 参数时,“useParam”钩子 returns 未定义。
import React, { useEffect } from "react";
import {
Link,
useSearchParams,
useNavigate,
useParams,
} from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import Message from "../components/Message";
import {
Row,
Col,
ListGroup,
Image,
Form,
Button,
Card,
} from "react-bootstrap";
import { addToCart } from "../actions/cartActions";
import { disable } from "colors";
const CartScreen = () => {
const { productID } = useParams();
console.log(productID);
const [qtyString] = useSearchParams();
const qty = Number(qtyString.toString().split("=")[1]);
console.log(qty)
const dispatch = useDispatch();
useEffect(() => {
if (productID) {
dispatch(addToCart(productID, qty));
}
}, [dispatch, productID, qty]);
return <div>CartScreen</div>;
};
export default CartScreen;
你介意教我如何从路由器获取参数(“id”)吗?任何帮助,将不胜感激。 谢谢,
这里的参数叫做id
:<Route path="/cart/:id" element={<CartScreen />} />
您做对了产品:const { id } = useParams();
但在购物车中您将其命名为 productID
:
const { productID } = useParams();
console.log(productID);
改为:
const { id } = useParams();
console.log(id);
所以你的问题就在这条线上
const { productID } = useParams(); <=========
在这里你必须输入你在路由中定义的相同名称,在你的情况下是 :id
见下文
<Route path="/product/:id" element={<ProductScreen />} />
所以你需要做的是:
const { id } = useParams();