React函数组件中的URI参数

18

如何在一个函数式的React组件中正确地读取URI参数?

在JavaScript中,如果该组件是Switch的直接子元素,我们可以这样做:

function MyComponent(props) {
    const query = props.location.search;
    // ...
}

如果该组件不是 Switch 的直接子级,我们可以使用一个类:

class MyComponent extends Component<RouteComponentProps> {
    render() {
        const query = this.props.location.search;
        // ...
    }
}

export default withRouter(MyComponent);

在严格的 TypeScript 中如何使用函数式组件?

我们希望 location 属性(如果有其他属性也一样)能够被某个 interfacetype 预定义并且由 React 提供,而不是组件的使用者提供。一个丑陋的方法是自己定义这个接口,然后期望它实际上就是这样。

4个回答

18
//use useParams 
import { useParams } from 'react-router-dom';

const params = useParams()

// yuo can find all params from here
console.log(params)

虽然这段代码片段可能解决了问题,但它并没有解释为什么或者如何回答这个问题。请在您的代码中包含解释,因为这真的有助于提高您的帖子质量。记住,您正在为未来的读者回答问题,而这些人可能不知道您提出代码建议的原因。您可以使用[编辑]按钮改进此答案以获得更多的投票和声望! - Brian Tompsett - 汤莱恩

10

正如Domino987在他们的回答中所说,解决方案是简单地扩展道具接口:

import * as React from "react";
import {withRouter, RouteComponentProps} from "react-router";

function MyComponent(props: MyComponentProps) {
    const query = props.location.search;

    return <span>Query: {query}, myField: {props.myField}</span>;
}

interface MyComponentProps extends RouteComponentProps {
    myField: string;
}

export default withRouter(MyComponent);

const query = props.match.params.id ==> id 是我的查询参数。它可以在函数组件中访问。非常感谢; - gnganapath
刚刚意识到,React 16.13 可以在路由中使用 map,例如:<Route path="/update-employee/:id" exact component={UpdateEmployee} />。在子组件中,我们可以传递 props 并获取 props.match.params.{yourVarble}。它正在工作。 - gnganapath

7
如果您将组件(函数或类)包装在withRouter中,则props会扩展自react-router的RouteComponentProps,并且可以正确设置,就像您在第二个示例中所做的那样。要访问正确的params参数,您必须像这样扩展props:
RouteComponentProps<{ id?: string; }>

这将让 TypeScript 知道,您具有匹配的属性,其字段 id 是可选的。现在,您可以使用 props.match.params.id 安全地访问它们的类型。您还可以扩展它以适应其他参数。

希望这可以帮助您。愉快编码!


我已经找到了解决方案。现在当我阅读这个时,我相信它指向了同样的方向。关键是使用 RouteComponentProps 扩展您的接口,看起来很有效。虽然,我实际上不理解 id?: string 部分。这是默认缺少的 RouteComponentProps 接口的某个属性吗?这就是为什么我们需要手动添加它的原因吗? - Snackoverflow
1
因为您可以按照自己的意愿创建路由。由于匹配参数可以是任何您想要的,例如:<Route path='/analytics/:id?' component={this.renderAnalytics} />,您必须告诉 TypeScript 您将其设置为什么。它也可以是 abalyticID 或 selectedAnalytic。 - Domino987
啊哈,是的。我刚从 https://reacttraining.com/react-router/core/api/match 上读到了关于 match 的内容。之前并不知道这个方法。 - Snackoverflow

6

对于函数式组件,请使用以下代码

包括:

import { BrowserRouter as Router, Switch, Route, Redirect, useLocation
} from 'react-router-dom'

在你的函数组件中定义函数:

const useQuery= () => {
       return new URLSearchParams(useLocation().search);
}

调用函数:

let query = useQuery();

获取查询字符串的参数:

console.log("Get data==>",query.get('logout'));

URL: http://localhost:8080/login?logout=false

输出:

Get data==> false

谢谢你的回答,看起来很酷,我想试一试。 - Snackoverflow
1
即使我们不使用 useQuery,这个利用 useLocation 的解决方案仍然比使用 withRouter 更加优雅。 - Naveen Attri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接