如何使用 React router v6 将参数传递到链接中?

Ber*_*ren 47 reactjs react-router react-router-dom

这是我的主要部分类,其中保留了链接的所有路由

export default class Section extends React.Component {
    render() {
        return (
            <div style={{backgroundColor:"white"}}>
                   <Routes>
                   <Route path="/"  element={<Home/>} />
                    <Route path="/discover" element={<Discover/>}   />
                    <Route path="/shop/makeup" element={<Makeup/>}  />
                    <Route path="/home/:id" element={<DetailsPage/>}  />
                    </Routes>
            </div>
        )}}
Run Code Online (Sandbox Code Playgroud)

这是我的卡片页面,它正在从上下文中获取数据。

import React from 'react';
import {DataContext} from './CardData.js';
import {Link} from 'react-router-dom'
import '../App.css';
export default class HomeCard extends React.Component {
    static contextType = DataContext;
    render(){
        const {products} = this.context;
  return (
    <div>
      <div className="card">
                { products.map((val,index)=>{
                   return(
                    <div className="card" key={val.id}>
                    <Card style={{ width: '14rem' }}  className="cardhead">
  <Card.Img variant="top" src={val.imgsrc} className="cardimg"/>
  <Card.Body>
    <Card.Text>{val.mname}
    </Card.Text>
    <Card
Run Code Online (Sandbox Code Playgroud)

从这里我使用 LINK 将 val.id 传递到页面的 url

    <Link to={`/home/${val.id}`}>
    <Button className="overlay" variant="primary">
      {/* <a  style={{color:"white"}} href={props.link} className="card-link">View</a> */}
      View</Button> </Link>
    <Card.Text><strong>{val.price}</strong>
    </Card.Text>
    <Card.Text><strong>{val.id}</strong>
    </Card.Text>
    </Card.Footer>
  </Card.Body>
</Card>
</div>);                
    </div>
  )}}
Run Code Online (Sandbox Code Playgroud)

我想访问我的产品详细信息页面的链接网址,如下所示:

export default class DetailsPage extends React.Component {
    static contextType = DataContext;
    state = {
        product: []
    }
    getProduct = () =>{
        if(this.props.match.params.id){
            const res = this.context.products;
            const data = res.filter(item =>{
                return item.id === this.props.match.params.id
            })
            this.setState({product: data})
        }};
    componentDidMount(){
        this.getProduct();
    }
    render() {
        const {product} = this.state;
        const {addCart} = this.context;
        return (
            <>
                {product.map(item =>(
                        <div className="details" key={item.id}>
                            <img src={item.imgsrc} alt=""/>
                            <div className="box">
                                <div className="row">
                                    <h2>{item.mname}</h2>
                                    <span>${item.price}</span>
                                </div>
                                <Link to="/cart" className="cart" onClick={() => addCart(item.id)}>
                                    Add to cart
                                </Link>
                            </div>   </div>  ))} </> )  }}
Run Code Online (Sandbox Code Playgroud)

不幸的是,它给出了一个错误,说 TypeError: Cannot read property 'params' of undefined

jas*_*ard 62

使用react-router-dom v6

父组件(应用程序)

<Route path="/something/:id" element={<Something />} />
Run Code Online (Sandbox Code Playgroud)

子组件(某物)

import { useParams } from "react-router-dom";

const Something = (props) => {

    let { id } = useParams(); 

    useEffect(() => {
        console.log(`/something/${id}`);
    },[]);

    // .....

}
Run Code Online (Sandbox Code Playgroud)

  • 快速而准确的解决方案。感谢您提供详细信息。这很有帮助。 (4认同)

Dre*_*ese 44

问题)

  1. 通过 prop 渲染的React-router-dom v6Route组件element不会接收路由 props
  2. 路由子组件必须使用 React hooks 来访问路由上下文,即useParamsuseLocationuseNavigate等......因此必须是函数组件。
  3. 不再存在withRouter高阶组件。

解决方案

DetailsPage是一个基于类的组件,因此我看到了几个用于访问路由的匹配参数的选项。

  1. 转换DetailsPage为函数组件并使用useParamsreact hook。
  2. 编写您自己的withRouterHOC 来访问路由上下文,并将任何 React-hook 可访问值作为 props 传递。

我不会介绍将基于类的组件转换为函数组件,但可以提供一个简单的 HOC 解决方案来传递给DetailsPage或任何其他基于类的组件)匹配参数。

const withRouter = WrappedComponent => props => {
  const params = useParams();
  // etc... other react-router-dom v6 hooks

  return (
    <WrappedComponent
      {...props}
      params={params}
      // etc...
    />
  );
};
Run Code Online (Sandbox Code Playgroud)

现在,您可以按照 v4/v5 中非常熟悉的方式包装和导出基于类的组件。

  • 这应该在文档中以某种方式突出显示。 (6认同)
  • @BramVanroy 从 React 的角度来看,他们已经非常清楚地表明函数组件是 React 的未来;它们只是仍然支持类组件以实现兼容性。自从[16.8.0中引入hooks](https://reactjs.org/blog/2019/02/06/react-v16.8.0.html)以来,我的团队还没有编写过一个类组件。那是近3年的时间了。我可以理解为什么像“react-router-dom”这样的库发布了一个重大更新,并且有效地进行了完全重写。IIRC 有一个 RRD 博客解释了 v6 更改的推动力,但官方文档也帮助解释了原因。 (5认同)

Han*_*ani 30

通过 React Router v6 中的 Link 组件通过一个名为statelike的单独 prop 传递 props <Link to="/" state={{ foo: bar }}>

例子:

   <Link
      to={`/login`}
      state={{ from: "the-page-id" }}
   >
      Login to see this page
   </Link>
Run Code Online (Sandbox Code Playgroud)

并使用钩子检索它useLocation()

import { useLocation } from "react-router-dom";
...
  const location = useLocation();
  const { from } = location.state;
  console.log(from); // output: "the-page-id"
Run Code Online (Sandbox Code Playgroud)

这应该仅与函数组件一起使用,而不是与类组件一起使用。


小智 21

我遇到了同样的问题,并在互联网上搜索了一个简单的解决方案。我不想将所有类组件重写为功能组件,但我想我可能必须这样做。但是,我将 withRouter 函数与 useParams() 一起使用,它工作得非常好并且很容易遵循。

要解决您的问题,以便您不必将 DetailsPage 类重写为函数,请按照下列步骤操作:

  1. 在类的开头添加以下代码行:

     import { useParams } from 'react-router-dom';
    
    Run Code Online (Sandbox Code Playgroud)
  2. 然后将此函数添加到您的类上方(准确复制):

     export function withRouter(Children){
         return(props)=>{
    
            const match  = {params: useParams()};
            return <Children {...props}  match = {match}/>
        }
      }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 接下来,将类定义更改为:

     class DetailsPage extends React.Component {
    
    Run Code Online (Sandbox Code Playgroud)
  4. 在类末尾添加以下代码行:

     export default withRouter(DetailsPage);
    
    Run Code Online (Sandbox Code Playgroud)

  • 这对于类组件来说非常有效。谢谢,你节省了很多时间 (3认同)

Mad*_*oop 10

以编程方式导航

发送参数至useNavigate

const navigate = useNavigate();
Run Code Online (Sandbox Code Playgroud)
 function _navigateToPage (pageNumber) {
    const page = pageNumber
    const title = "Hello World";
    navigate("/fragment", {
      state:{
          page,
          title
        },
    });

  }
Run Code Online (Sandbox Code Playgroud)

检索其他页面中的参数useLocation

 function _navigateToPage (pageNumber) {
    const page = pageNumber
    const title = "Hello World";
    navigate("/fragment", {
      state:{
          page,
          title
        },
    });

  }
Run Code Online (Sandbox Code Playgroud)