Реакция - Как получить значение параметра из строки запроса


414

Как я могу определить маршрут в моем файле rout.jsx, чтобы захватить __firebase_request_keyзначение параметра из URL, сгенерированного процессом единого входа Twitter после перенаправления с их серверов?

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
прискорбно, что в вопросе написано «строки запроса», но на самом деле
задан

6
query strings"? var1 = val & var2 = val2" url paramters
Мэддокс

Ответы:


484

React Router 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 .

Например, с импортированной библиотекой qs, как qsвы могли бы сделать

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

Другой библиотекой будет строка запроса . Посмотрите этот ответ, чтобы узнать больше о разборе строки поиска. Если вам не нужна IE-совместимость, вы также можете использовать

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

Для функциональных компонентов вы бы заменили this.props.locationна ловушку useLocation . Обратите внимание, что вы можете использовать window.location.search, но это не позволит запускать рендеринг React при изменениях. Если ваш (нефункциональный) компонент не является прямым потомком, Switchвам нужно использовать withRouter для доступа к любому из реквизитов, предоставленных маршрутизатором.

генеральный

предложение nizam.sp сделать

console.log(this.props)

будет полезно в любом случае.


3
Для этого не требуется менять реагирующий маршрутизатор.
Кристиан

2
Я бы не предложил использовать console.dir()из-за предупреждения ... по крайней мере :)
boldnik

1
Ну, это просто для просмотра содержимого, один раз. Вы также можете просто поставить точку останова и оценить this.props в отладчике. В настоящее время даже console.log справится с этой задачей (по крайней мере, в Chrome вы можете расширить значения, напечатанные таким образом), и даже console.log не будет использоваться в производстве.
Кристиан

1
@ Кристиан В итоге я использовал простой JavaScript. const path = window.location.pathname; дает мне URL. Затем я могу разобрать это так, как мне нужно. Я поместил это в событие жизненного цикла componentWillMount в моем компоненте React.
Сэм

5
В react-router-domI должен был использовать , withRouterчтобы сделать эту работу!
демонофизист

188

React Router 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

Маршрутные реквизиты передаются в функцию рендеринга.


1
У меня была похожая проблема с доступом к query paramsтекущему URL моего приложения в дочернем компоненте с помощью React Router v4. Если вы ищете query params, this.props.location.query в React Router 4 был удален (в настоящее время используется v4.1.1). Смотрите этот ответ: stackoverflow.com/a/43630848/1508105
Алекс Джонсон

42
К сожалению, это не отвечает на этот вопрос, поскольку вы не обязательно получите, /users/?q=...но могли бы /user?q=.... Вам следует использовать this.props.location.searchReact Router v4 и проанализировать результаты самостоятельно, как описано в моем ответе ниже.
nbeuchat

Это правильный ответ. this.props.location.searchне существует.
NickJ

@NickJ: какую версию React Router вы используете?
nbeuchat

126

React Router v3

С React Router v3 вы можете получить строку запроса из this.props.location.search(? Qs1 = naisarg & qs2 = parmar). Например, с let params = queryString.parse(this.props.location.search), даст{ qs1 : 'naisarg', qs2 : 'parmar'}

React Router 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
зачем вам вообще нужна библиотека, когда вы можете использовать URLSearchParams
SuperUberDuper

3
@SuperUberDuper из-за Edge и iOS Safari - developer.mozilla.org/en-US/docs/Web/API/…
Брайан Бернс

3
Конечно, но тогда просто используйте полифилл URLSearchParams
Энтони Мэннинг-Франклин

67

Насколько я знаю, есть три способа сделать это.

1. использовать регулярное выражение для получения строки запроса.

2.Вы можете использовать браузер API. image текущий 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. если текущий URL выглядит следующим образом:

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

URLSearchParams не поддерживается IE (если это актуально для всех :)
Кристиан

@Christian Typical IE
Тревор Вуд

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
@ Крис var prefixed = qs.parse('?a=b&c=d', { ignoreQueryPrefix: true });должен это исправить. Пример найден здесь: github.com/ljharb/qs
Алан Шапира

38

При использовании React-хуков нет доступа к доступу this.props.location. Для захвата параметров URL используйте windowобъект.

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

1
Это прекрасный ответ. Спасибо.
LukeVenter

Вы можете использовать «useLocation» из «act-router-dom »вместо объекта окна для достижения тех же результатов.
Часмату

1
URLSearchParams не поддерживается IE developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/...
Майкл Freidgeim

Кроме того, доступ к window.location не позволит запустить повторную визуализацию React при изменениях.
христианин

25

React Router v4

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

Пожалуйста, обратите внимание, что это в настоящее время экспериментально.

Проверьте совместимость браузера здесь: https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams#Browser_compatibility


2
Хорошее решение, но, к сожалению, IE не поддерживает ((
Андрей Пацейко

@AndreyPatseiko есть полифилл для этого github.com/WebReflection/url-search-params
Earlee

23

Вы можете проверить реагирующий маршрутизатор , просто, вы можете использовать код для получения параметра запроса, если вы определили его в вашем маршрутизаторе:

this.props.params.userId

25
Это не правильный ответ в случае ОП. props.paramsпредназначен для параметров URL (сегмент URL с префиксом «:» в маршрутизаторе реагирования), props.location.queryхранит параметры строки запроса (после «?») и является тем, что хочет OP.
Матье Харле

21

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}/>

Вы получите этот идентификатор, как это

this.props.match.params.id

Кто-нибудь знает, как это работает в React Router 5.0.1? this.props.match.params всегда пусто.
Марк А. Тальяферро

2
@ MarkA.Tagliaferro Пропорция доступна только для компонентов, визуализируемых Маршрутом. Если это не относится к вашему компоненту, вы можете получить к ним доступ, поместив свой компонент в withRouter HOC.
Джимми Лонгли


11

Если вы не получаете this.props... вы ожидали, основываясь на других ответах, вам может потребоваться использовать withRouter( docs 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-реагировать

Требования

response-router-dom ":" ^ 4.3.1 "

Решение

В месте, где указан маршрутизатор

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

Добавьте имя параметра, который вы хотите передать следующим образом

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

На странице, на которой вы рендерингуете / path, вы можете указать это для просмотра имени параметра с идентификатором вызова следующим образом

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

type Props = RouteComponentProps <{id: number}>;
Детям

класс MyClass расширяет React.PureComponent <Props> {
pfeds

Затем в componentDidMount (например), const myId = this.props.match.params.id;
Детям

7

React routerс v4 и далее больше не дает вам query paramsнепосредственно в своем locationобъекте. Причина в том,

Существует ряд популярных пакетов, которые выполняют синтаксический разбор / строковую обработку запроса немного по-разному, и каждое из этих различий может быть «правильным» способом для одних пользователей и «неправильным» для других. Если бы React Router выбрал «правильный», он был бы правильным только для некоторых людей. Затем необходимо добавить способ, которым другие пользователи могут заменять свои предпочтительные пакеты для разбора запросов. React Router не использует внутреннюю строку поиска, которая требует, чтобы он анализировал пары ключ-значение, поэтому нет необходимости выбирать, какая из них должна быть «правильной».

Включив это, было бы более разумно просто проанализировать location.search в ваших компонентах представления, ожидающих объект запроса.

Вы можете сделать это в общем, переопределив withRouterиз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
Добро пожаловать в переполнение стека! Пожалуйста, не отвечайте только с исходным кодом. Попробуйте дать хорошее описание того, как работает ваше решение. Смотрите: Как мне написать хороший ответ? , Спасибо
sɐunıɔ ןɐ qɐp

1
Вероятно, собирается получить «данные» не определено no-undef
Том Стиккель

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>
  )
}

Большое вам спасибо за предоставление такой простой, но отличный крюк!
1

5

this.props.params.your_param_name будет работать.

Это способ получить параметры из строки запроса.
Пожалуйста, сделайте, console.log(this.props);чтобы изучить все возможности.


3

В компоненте, где вам нужно получить доступ к параметрам, вы можете использовать

this.props.location.state.from.search

который покажет всю строку запроса (все после ?знака)


3

Скажи, что есть URL-адрес следующим образом

HTTP: // локальный: 3000 / обратного вызова код = 6c3c9b39-de2f-3bf4-a542-3e77a64d3341

Если мы хотим извлечь код из этого URL, будет работать следующий метод.

const authResult = new URLSearchParams(window.location.search); 
const code = authResult.get('code')

Спасибо!! Идеальный ответ.
Таха Фаруки

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

Когда вы работаете с реагирующим маршрутом, dom затем будет очищать объект с помощью for match, но если вы выполните следующий код, то это будет для компонента 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>

Таким образом, вы можете получить реквизит и сопоставить параметры и идентификатор профиля

Это сработало для меня после долгих исследований компонента 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 });
      });
  }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.