React - Як отримати значення параметра з рядка запиту


412

Як я можу визначити маршрут у моєму файлі route.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
прикро, що питання говорить про "рядки запиту", але насправді задає питання про "параметри URL-адреси"
SeanMC

6
query strings"? var1 = val & var2 = val2",: " url paramters/ фотографії /: companyiD / new"
Maddocks

Відповіді:


484

Реагує маршрутизатор v3

Маршрутизатор React вже аналізує розташування для вас і передає його вашому 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, але це не дозволить запустити реагування на зміни. Якщо ваш (нефункціональний) компонент не є прямим дочірнім користувачем, Switchвам потрібно скористатися withRouter для доступу до будь-якого з реквізитів, що надаються маршрутизатором.

Загальні

Пропозиція nizam.sp зробити

console.log(this.props)

буде корисно в будь-якому випадку.


3
Змінювати маршрутизатор реагування на нього не потрібно.
Крістіан

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

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

1
@Christian Я в кінцевому підсумку використовував просто звичайний JavaScript. const path = window.location.pathname; дає мені URL. Тоді я можу розібрати його так, як мені потрібно. Я розмістив це в події життєвого циклу компонента WillMount у своєму компоненті React.
Сем

5
У react-router-domмені довелося скористатися, withRouterщоб зробити цю роботу!
демонофтеміст

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

Реквізити маршруту передаються функції візуалізації.


1
У мене була аналогічна проблема з доступом до query paramsпоточної URL-адреси мого додатка в дочірньому компоненті за допомогою React Router v4. Якщо ви шукаєте це query params, цей.props.location.query в React Router 4 видалено (наразі використовується v4.1.1). Дивіться цю відповідь: stackoverflow.com/a/43630848/1508105
Алекс Джонсон

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
навіщо вам навіть потрібна ліб, коли ви можете використовувати URLSearchParams
SuperUberDuper

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

3
Впевнені, але тоді просто використовуйте поліфайл URLSearchParams
Ентоні Маннінг-Франклін

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. якщо поточна 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

IE не підтримує URLSearchParams (якщо це актуально для когось :)
Крістіан

@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'}
Кріс

2
@Chris 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" від "react-router-dom" замість об'єкта window для досягнення тих же результатів.
Часмату

1
URLSearchParams не підтримується IE developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/…
Michael Freidgeim

Крім того, доступ до window.location не дозволить викликати повторне відображення React щодо змін.
Крістіан

25

Реагує маршрутизатор 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зберігає параметри рядків запитів (після '?') і те, чого хочеться ОП.
Матьє Харле

20

Маршрутизатор React 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.
Джиммі Лонглі

13

За допомогою цього одного вкладиша ви можете використовувати його будь-де в обох компонентах React Hook та React Class, використовуючи звичайний JavaScript.

https://www.hunterisgod.com/?city=Leipzig

let city = (new URLSearchParams(window.location.search)).get("city")

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-react

Вимоги

react-router-dom ":" ^ 4.3.1 "

Рішення

У місці, де вказано маршрутизатор

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

Додайте ім'я параметра, яке ви хочете передати так

<Route path="some/path/: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}> ??
Чоко

введіть реквізити = RouteComponentProps <{id: номер}>;
pfeds

клас MyClass розширює React.PureComponent <Props> {
pfeds

Потім у компонентDidMount (наприклад), const myId = this.props.match.params.id;
pfeds

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

Дуже дякую за надання такого простого, але чудового гачка!
chr1s

5

this.props.params.your_param_name буду працювати.

Це спосіб отримати парами з рядка запиту.
Будь ласка, зробіть, console.log(this.props);щоб вивчити всі можливості.


3

У компоненті, де вам потрібно отримати доступ до параметрів, які ви можете використовувати

this.props.location.state.from.search

який розкриє весь рядок запиту (усе після ?знака)


2

У React Router v4 лише правильний шлях

Ви можете отримати доступ до властивостей об'єкта історії та найближчої відповідності через компонент вищого порядку 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>

Таким чином, ви можете отримати реквізит і збігнути параметри та ідентифікатор профілю

Це працювало для мене після безлічі досліджень компонента 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.