React-如何从查询字符串获取参数值


412

__firebase_request_key从服务器重定向后,如何在我的routes.jsx文件中定义路由以从Twitter的单点登录过程生成的URL 捕获参数值?

http://localhost:8000/#/signin?_k=v9ifuf&__firebase_request_key=blablabla

我尝试使用以下路由配置,但:redirectParam没有捕获上述参数:

<Router>
  <Route path="/" component={Main}>
    <Route path="signin" component={SignIn}>
      <Route path=":redirectParam" component={TwitterSsoButton} />
    </Route>
  </Route>
</Router>

1
有一个Github上讨论,在这里
VSYNC

3
不幸的是,这个问题说的是“查询字符串”,但实际上是在询问“ URL参数”
SeanMC

6
query strings“?var1 = val&var2 = val2”,:“ url paramters/ photos /:companyiD / new”
Maddocks

Answers:


484

反应路由器v3

React Router已经为您解析了位置并将其作为道具传递给RouteComponent。您可以通过访问查询(在URL中的?之后)部分

this.props.location.query.__firebase_request_key

如果要查找路径参数值(在路由器内部用冒号(:)分隔),则可以通过以下方式访问它们

this.props.match.params.redirectParam

这适用于最新的React Router v3版本(不确定哪个版本)。据报使用较旧的路由器版本this.props.params.redirectParam

通用React Router v4和React Router v5

React Router v4不再为您解析查询,但您只能通过进行访问this.props.location.search。由于某些原因,请参阅nbeuchat的答案

例如,您可以导入qsqs

qs.parse(this.props.location.search, { ignoreQueryPrefix: true }).__firebase_request_key

另一个库是query-string。有关解析搜索字符串的更多想法,请参见此答案。如果不需要IE兼容性,也可以使用

new URLSearchParams(this.props.location.search).get("__firebase_request_key")

对于功能组件,您将替换this.props.location为hook useLocation。请注意,您可以使用window.location.search,但这不允许在更改时触发React渲染。如果您的(非功能性)组件不是的直接子代,则Switch需要使用withRouter来访问任何路由器提供的道具。

一般

nizam.sp的建议

console.log(this.props)

在任何情况下都会有帮助。


3
不需要为其更改反应路由器。
基督教徒

2
console.dir()由于警告提示,我不建议使用...至少:)
boldnik '16

1
好吧,这只是一次查看内容。您也可以在调试器中放置一个断点并评估this.props。如今,即使console.log也能胜任(至少在Chrome中,您可以扩展打印出的值)-甚至console.log也已不在生产中使用。
基督教徒

1
@Christian我最终只使用普通的javascript。const path = window.location.pathname; 给我URL。然后,我可以按照需要的方式对其进行解析。我将其放在React组件的componentWillMount生命周期事件中。
山姆

5
react-router-dom我不得不用来withRouter使这项工作!
demonofthemistist

188

反应路由器v4

使用 component

<Route path="/users/:id" component={UserPage}/> 

this.props.match.params.id

组件将使用路线道具自动渲染。


使用 render

<Route path="/users/:id" render={(props) => <UserPage {...props} />}/> 

this.props.match.params.id

路线道具将传递给render函数。


1
query params使用React Router v4在子组件中访问应用程序当前URL时遇到类似问题。如果您正在寻找,则query paramsReact Router 4中的this.props.location.query已被删除(当前使用v4.1.1)。看到这个答案: stackoverflow.com/a/43630848/1508105
Alex Johnson

41
不幸的是,这并不能回答问题,因为您不一定要拥有,/users/?q=...但可以拥有/user?q=...。您应该this.props.location.search在React Router v4中使用并自己解析结果,如下面我的回答所述。
nbeuchat

这是正确的答案。this.props.location.search不存在。
NickJ

@NickJ:您使用哪个版本的React Router?
nbeuchat

126

反应路由器v3

使用React Router v3,您可以从this.props.location.search(?qs1 = naisarg&qs2 = parmar)获取查询字符串。例如,使用let params = queryString.parse(this.props.location.search),将得出{ qs1 : 'naisarg', qs2 : 'parmar'}

反应路由器v4

使用React Router v4,this.props.location.query不再存在。您需要改用this.props.location.search自己或使用现有包(例如)来解析查询参数query-string

这是一个使用React Router v4和query-string库的最小示例。

import { withRouter } from 'react-router-dom';
import queryString from 'query-string';

class ActivateAccount extends Component{
    someFunction(){
        let params = queryString.parse(this.props.location.search)
        ...
    }
    ...
}
export default withRouter(ActivateAccount);

合理的

React Router团队删除该query属性的理由是:

有许多流行的软件包在查询字符串解析/字符串化方面略有不同,并且对于某些用户而言,这些差异中的每一个可能都是“正确”的方式,对于其他用户而言可能是“不正确的”方式。如果React Router选择了“正确的”路由器,那对某些人来说将是正确的。然后,将需要为其他用户添加一种替代方式,以替代其首选查询解析包。React Router并没有内部使用搜索字符串,它不需要它来解析键值对,因此它不需要选择其中哪一个应该是“正确的”。

[...]

4.0版采用的方法是去除所有“包含电池”的功能,然后回到基本的布线。如果您需要查询字符串解析或异步加载或Redux集成或其他非常特定的内容,则可以使用专门针对您的用例的库来添加它。不需要的东西少了很多,您可以根据自己的喜好和需求自定义内容。

您可以在GitHub上找到完整的讨论。


1
完美运作。自2018
。– mmla

4
为什么你甚至需要一个lib时,你可以使用URLSearchParams
SuperUberDuper

3
@SuperUberDuper因为边缘和iOS的Safari浏览器- developer.mozilla.org/en-US/docs/Web/API/...
布赖恩·伯恩斯

3
当然可以,但是只需使用URLSearchParams polyfill
Anthony Manning-Franklin

67

据我所知,您可以通过三种方法进行操作。

1.使用正则表达式获取查询字符串。

2.您可以使用浏览器api。图片当前的URL是这样的:

http://www.google.com.au?token=123

我们只想得到123;

第一

 const query = new URLSearchParams(this.props.location.search);

然后

const token = query.get('token')
console.log(token)//123

3.使用第三个名为“查询字符串”的库。首先安装

npm i query-string

然后将其导入到当前的javascript文件中:

 import queryString from 'query-string'

下一步是在当前URL中获取“令牌”,请执行以下操作:

const value=queryString.parse(this.props.location.search);
const token=value.token;
console.log('token',token)//123

希望能帮助到你。

于25/02/2019更新

  1. 如果当前网址如下所示:

http://www.google.com.au?app=home&act=article&aid=160990

我们定义一个函数来获取参数:

function getQueryVariable(variable)
{
        var query = window.location.search.substring(1);
        console.log(query)//"app=article&act=news_content&aid=160990"
        var vars = query.split("&");
        console.log(vars) //[ 'app=article', 'act=news_content', 'aid=160990' ]
        for (var i=0;i<vars.length;i++) {
                    var pair = vars[i].split("=");
                    console.log(pair)//[ 'app', 'article' ][ 'act', 'news_content' ][ 'aid', '160990' ] 
        if(pair[0] == variable){return pair[1];}
         }
         return(false);
}

我们可以通过以下方式获得“援助”:

getQueryVariable('aid') //160990

IE不支持URLSearchParams(如果与任何人都相关:)
基督教

@Christian典型的IE
Trevor Wood

66

React Router v4不再具有该 props.location.query 对象(请参见github讨论)。因此,可接受的答案不适用于较新的项目。

v4的解决方案是使用外部库查询字符串来解析props.location.search

const qs = require('query-string');
//or
import * as qs from 'query-string';

console.log(location.search);
//=> '?foo=bar'

const parsed = qs.parse(location.search);
console.log(parsed);
//=> {foo: 'bar'}

1
由于某些原因,qs.parse导致:{'?foo': 'bar'}
克里斯(Chris)

2
@Chris var prefixed = qs.parse('?a=b&c=d', { ignoreQueryPrefix: true });应该修复它。可在此处找到示例:github.com/ljharb/qs
Alan Schapira

38

使用React钩子时,无法访问this.props.location。要捕获url参数,请使用window对象。

const search = window.location.search;
const params = new URLSearchParams(search);
const foo = params.get('bar');

1
这是一个很好的答案。谢谢。
LukeVenter

您可以使用“ react-router-dom”中的“ useLocation”而不是window对象来获得相同的结果。
Chasmatu


另外,访问window.location将不允许在更改时触发React的重新渲染。
基督教

25

反应路由器v4

const urlParams = new URLSearchParams(this.props.location.search)
const key = urlParams.get('__firebase_request_key')

请注意,它目前处于实验阶段。

在此处检查浏览器兼容性:https : //developer.mozilla.org/zh-CN/docs/Web/API/URLSearchParams/URLSearchParams#Browser_compatibility


2
好的解决方案,但不幸的是IE不支持((
Andrey Patseiko


23

您可以简单地检查 react-router,只要您在路由器中定义,就可以使用代码获取查询参数:

this.props.params.userId

25
对于OP,这不是正确的答案。props.params用于URL参数(在React Router中以“:”为前缀的URL段),props.location.query存储查询字符串参数(在“?”之后),这是OP想要的。
MatthieuHarlé'1

20

React Router 5.1+

5.1推出各种钩子状useLocation,并useParams可能是使用在这里。

例:

<Route path="/test/:slug" component={Dashboard} />

那如果我们拜访说

http://localhost:3000/test/signin?_k=v9ifuf&__firebase_request_key=blablabla

您可以像检索它

import { useLocation } from 'react-router';
import queryString from 'query-string';

const Dashboard: React.FC = React.memo((props) => {
    const location = useLocation();

    console.log(queryString.parse(location.search));

    // {__firebase_request_key: "blablabla", _k: "v9ifuf"}

    ...

    return <p>Example</p>;
}

17

如果您的路由器是这样的

<Route exact path="/category/:id" component={ProductList}/>

你会得到这样的ID

this.props.match.params.id

有谁知道这在React Router 5.0.1中如何工作?this.props.match.params始终为空。
Mark A. Tagliaferro

2
@ MarkA.Tagliaferro该道具仅可用于由路线渲染的组件。如果不是您的组件,则可以通过将组件包装在withRouter HOC中来访问它们。
吉米·隆利


11

如果您没有得到this.props...,而您期望根据其他答案,则可能需要使用withRouterdocs v4):

import React from 'react'
import PropTypes from 'prop-types'
import { withRouter } from 'react-router'

// A simple component that shows the pathname of the current location
class ShowTheLocation extends React.Component {
  static propTypes = {
    match: PropTypes.object.isRequired,
    location: PropTypes.object.isRequired,
    history: PropTypes.object.isRequired
  }

  render() {
    const { match, location, history } = this.props

    return (
      <div>You are now at {location.pathname}</div>
    )
  }
}

// Create a new component that is "connected" (to borrow redux terminology) to the router.  
const TwitterSsoButton = withRouter(ShowTheLocation)  

// This gets around shouldComponentUpdate
withRouter(connect(...)(MyComponent))

// This does not
connect(...)(withRouter(MyComponent))

8

我很难解决这个问题。如果以上方法均无效,则可以尝试使用此方法。我正在使用create-react-app

要求

react-router-dom“:“ ^ 4.3.1”

在指定路由器的位置

<Route path="some/path" ..../>

添加您想要传递的参数名称

<Route path="some/path/:id" .../>

在呈现某些/路径的页面上,您可以指定此名称以查看参数名称的呼叫ID,如下所示

componentDidMount(){
  console.log(this.props);
  console.log(this.props.match.params.id);
}

在导出默认值的最后

export default withRouter(Component);

记住要包括导入

import { withRouter } from 'react-router-dom'

当console.log(this.props)时,您将能够传递下来。玩得开心!


2
如果使用TypeScript,请不要忘记添加RouteComponentProps<{id: number}>
-ThunderDev

1
在哪里添加RouteComponentProps <{id:number}>?
Choco '18

类型Props = RouteComponentProps <{id:number}>;
pfeds

类MyClass扩展了React.PureComponent <Props> {
pfeds

然后在componentDidMount中(例如),const myId = this.props.match.params.id;
pfeds

7

React router从v4开始,不再为您query params直接提供其location对象。原因是

有许多流行的软件包在查询字符串解析/字符串化方面略有不同,并且对于某些用户而言,这些差异中的每一个可能都是“正确”的方式,对于其他用户而言可能是“不正确的”方式。如果React Router选择了“正确”的路由器,那对某些人来说将是正确的。然后,将需要为其他用户添加一种替代方式,以替代其首选查询解析包。React Router并没有内部使用搜索字符串,它不需要它来解析键值对,因此它不需要选择其中哪一个应该是“正确的”。

包含了这一点之后,仅在需要查询对象的视图组件中解析location.search才有意义。

您可以通过覆盖withRouterfrom react-router等来通用地执行此操作

customWithRouter.js

import { compose, withPropsOnChange } from 'recompose';
import { withRouter } from 'react-router';
import queryString from 'query-string';

const propsWithQuery = withPropsOnChange(
    ['location', 'match'],
    ({ location, match }) => {
        return {
            location: {
                ...location,
                query: queryString.parse(location.search)
            },
            match
        };
    }
);

export default compose(withRouter, propsWithQuery)

6
componentDidMount(){
    //http://localhost:3000/service/anas
    //<Route path="/service/:serviceName" component={Service} />
    const {params} =this.props.match;
    this.setState({ 
        title: params.serviceName ,
        content: data.Content
    })
}

4
欢迎使用Stack Overflow!请不要只回答源代码。尝试提供有关您的解决方案如何工作的很好的描述。请参阅:我如何写一个好的答案?。谢谢
sɐunıɔןɐqɐp

1
可能要获取“数据”未定义为
un

6

也许有点晚了,但是这个反应钩子可以帮助您在URL查询中获取/设置值:https//github.com/rudyhuynh/use-url-search-params(由我编写)。

无论有无,它都能工作react-router。下面是您的情况下的代码示例:

import React from "react";
import { useUrlSearchParams } from "use-url-search-params";

const MyComponent = () => {
  const [params, setParams] = useUrlSearchParams()
  return (
    <div>
      __firebase_request_key: {params.__firebase_request_key}
    </div>
  )
}

非常感谢您提供了这样一个简单但不错的方法!
chr1s

5

this.props.params.your_param_name 将工作。

这是从查询字符串中获取参数的方法。
请尽console.log(this.props);一切可能。


3

在需要访问参数的组件中,可以使用

this.props.location.state.from.search

它将显示整个查询字符串(?符号后的所有内容)


2

在React Router v4中,只有withRoute是正确的方法

您可以通过withRouter高阶组件访问历史对象的属性和最接近的匹配项。每当渲染时,withRouter都会将更新的匹配,位置和历史道具传递给包装的组件。

import React from 'react'
import PropTypes from 'prop-types'
import { withRouter } from 'react-router'

// A simple component that shows the pathname of the current location
class ShowTheLocation extends React.Component {
  static propTypes = {
    match: PropTypes.object.isRequired,
    location: PropTypes.object.isRequired,
    history: PropTypes.object.isRequired
  }

  render() {
    const { match, location, history } = this.props

    return (
      <div>You are now at {location.pathname}</div>
    )
  }
}

// Create a new component that is "connected" (to borrow redux
// terminology) to the router.
const ShowTheLocationWithRouter = withRouter(ShowTheLocation)

https://reacttraining.com/react-router/web/api/withRouter


2

我使用了一个名为query-string的外部包来解析url参数,就像这样。

import React, {Component} from 'react'
import { parse } from 'query-string';

resetPass() {
    const {password} = this.state;
    this.setState({fetching: true, error: undefined});
    const query = parse(location.search);
    return fetch(settings.urls.update_password, {
        method: 'POST',
        headers: {'Content-Type': 'application/json', 'Authorization': query.token},
        mode: 'cors',
        body: JSON.stringify({password})
    })
        .then(response=>response.json())
        .then(json=>{
            if (json.error)
                throw Error(json.error.message || 'Unknown fetch error');
            this.setState({fetching: false, error: undefined, changePassword: true});
        })
        .catch(error=>this.setState({fetching: false, error: error.message}));
}

2

当您使用react route dom时,将使用空对象进行匹配,但是如果您执行以下代码,则它将对es6组件以及直接对功能组件起作用

import { Switch, Route, Link } from "react-router-dom";

<Route path="/profile" exact component={SelectProfile} />
<Route
  path="/profile/:profileId"
  render={props => {
    return <Profile {...props} loading={this.state.loading} />;
  }}
/>
</Switch>
</div>

这样您就可以获取道具并匹配参数和配置文件ID

经过对es6组件的大量研究后,这对我有用。



1

或者也许是这样?

let win = {
  'location': {
    'path': 'http://localhost:8000/#/signin?_k=v9ifuf&__firebase_request_key=blablabla'
  }
}
if (win.location.path.match('__firebase_request_key').length) {
  let key = win.location.path.split('__firebase_request_key=')[1]
  console.log(key)
}


0

您可以创建简单的钩子,以从当前位置提取搜索参数:

import React from 'react';
import { useLocation } from 'react-router-dom';

export function useSearchParams<ParamNames extends string[]>(...parameterNames: ParamNames): Record<ParamNames[number], string | null> {
    const { search } = useLocation();
    return React.useMemo(() => { // recalculate only when 'search' or arguments changed
        const searchParams = new URLSearchParams(search);
        return parameterNames.reduce((accumulator, parameterName: ParamNames[number]) => {
            accumulator[ parameterName ] = searchParams.get(parameterName);
            return accumulator;
        }, {} as Record<ParamNames[number], string | null>);
    }, [ search, parameterNames.join(',') ]); // join for sake of reducing array of strings to simple, comparable string
}

那么您可以在功能组件内部使用它,如下所示:

// current url: http://localhost:8000/#/signin?_k=v9ifuf&__firebase_request_key=blablabla
const { __firebase_request_key } = useSearchParams('__firebase_request_key');
// current url: http://localhost:3000/home?b=value
const searchParams = useSearchParameters('a', 'b'); // {a: null, b: 'value'}

-2
export class ClassName extends Component{
      constructor(props){
        super(props);
        this.state = {
          id:parseInt(props.match.params.id,10)
        }
    }
     render(){
        return(
          //Code
          {this.state.id}
        );
}


-5

最简单的解决方案!

在路由中:

   <Route path="/app/someUrl/:id" exact component={binder} />

在反应代码中:

componentDidMount() {
    var id = window.location.href.split('/')[window.location.href.split('/').length - 1];
    var queryString = "http://url/api/controller/" + id
    $.getJSON(queryString)
      .then(res => {
        this.setState({ data: res });
      });
  }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.