React - Sorgu dizesinden parametre değeri nasıl alınır


413

__firebase_request_keyTwitter'dan tek oturum açma işleminin oluşturduğu bir URL'den sunucularından yeniden yönlendirmeden sonra elde edilen URL'den parametre değerini yakalamak için route.jsx dosyamda nasıl bir rota tanımlayabilirim ?

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

Aşağıdaki yollar yapılandırması ile denedim, ancak :redirectParambelirtilen param yakalamak değil:

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

1
Burada bir Github tartışması var
vsync

3
sorusuna "sorgu dizeleri" diyor ama aslında "url parametreleri" soruyor
talihsiz

6
query strings"? var1 = val & var2 = val2",: url paramters"/ photos /: şirket / yeni"
Maddocks

Yanıtlar:


484

React Router v3

React Router sizin için konumu zaten ayrıştırır ve sahne olarak RouteComponent'inize iletir . Sorguya (url'deki? After?) Bölümünden

this.props.location.query.__firebase_request_key

Yöneltici içinde iki nokta üst üste (:) ile ayrılmış path parametre değerlerini arıyorsanız, bunlara erişilebilir

this.props.match.params.redirectParam

Bu, geç React Router v3 sürümleri için geçerlidir (hangisi olduğundan emin değilsiniz). Eski yönlendirici sürümlerinin kullanıldığı bildirildi this.props.params.redirectParam.

React Router v4 ve React Router v5, genel

React Router v4, sorguyu artık sizin için ayrıştırmıyor, ancak yalnızca this.props.location.search . Nedenler için nbeuchat'ın cevabına bakınız .

Örneğin, qs kütüphanesiqs yapabileceğiniz

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

Başka bir kütüphane sorgu dizesi olacaktır . Arama dizesini ayrıştırma hakkında daha fazla fikir için bu cevaba bakın . IE uyumluluğuna ihtiyacınız yoksa yoksa,

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

Fonksiyonel bileşenler this.props.locationiçin hook useLocation ile değiştirirsiniz . Kullanabileceğinizi unutmayın, window.location.searchancak bu değişikliklerde Reaksiyon oluşturmayı tetiklemeye izin vermez. (İşlevsel olmayan) bileşeniniz doğrudan bir alt öğe değilse Switch, kullanmanız gerekir öğe değilse , sağlanan yönlendiricilerin herhangi birine erişmek için Yönlendirici ile .

Genel

nizam.sp'nin önerisi

console.log(this.props)

her durumda yardımcı olacaktır.


3
Reaksiyon yönlendiricisini değiştirmek gerekmez.
Christian

2
Uyarı notuconsole.dir() nedeniyle kullanmanızı tavsiye etmem ... en azından :)
boldnik

1
Sadece içeriğe bir kez bakmak için. Ayrıca sadece bir kırılma noktası ekleyebilir ve bunu değerlendirebilirsiniz. Hata ayıklayıcıdakirops. Günümüzde, console.log bile işi yapacak (en azından Chrome'da böyle yazdırılmış değerleri genişletebilirsiniz) - ve console.log bile üretimde kullanılacak bir şey değildir.
Christian

1
@Christian Ben sadece düz javascript kullanarak sona erdi. const yolu = window.location.pathname; bana URL’yi verir. Daha sonra ihtiyacım olan şekilde ayrıştırabilirim. Bunu React bileşenimdeki componentWillMount yaşam döngüsü olayına yerleştirdim.
Sam,

5
In react-router-domI kullanmak zorunda withRouterbu işi yapmak için!
demonofthemist

188

React Router v4

kullanma component

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

this.props.match.params.id

Bileşen otomatik olarak rota desteği ile oluşturulur.


kullanma render

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

this.props.match.params.id

Rota sahne render fonksiyonuna aktarılır.


1
query paramsReact Router v4 kullanarak bir alt bileşendeki uygulamamın geçerli URL'sine erişirken de benzer bir sorun yaşadım . Eğer arıyorsanız query params, this.props.location.query Router 4 (şu anda v4.1.1 kullanarak) kaldırıldı yanıt verin. Bu yanıta bakın: stackoverflow.com/a/43630848/1508105
Alex Johnson

41
Bu, ne yazık ki sahip olmayacağınız, /users/?q=...ancak sahip olabileceğiniz için maalesef soruyu cevaplamıyor /user?q=.... this.props.location.searchReact Router v4'te kullanmalı ve aşağıdaki cevabımda açıklandığı gibi sonuçları kendiniz ayrıştırmalısınız.
nbeuchat

Bu doğru cevap. this.props.location.searchmevcut değil.
NickJ

@NickJ: React Router'ın hangi sürümünü kullanıyorsunuz?
nbeuchat

126

React Router v3

React Router v3 ile, this.props.location.search(? Qs1 = naisarg & qs2 = parmar) ' dan sorgu dizesi alabilirsiniz . Örneğin, birlikte let params = queryString.parse(this.props.location.search), verecekti{ qs1 : 'naisarg', qs2 : 'parmar'}

React Router v4

React Router v4 ile this.props.location.queryartık mevcut değil. Bunun this.props.location.searchyerine kullanmanız ve sorgu parametrelerini kendiniz veya mevcut bir paketi kullanarak ayrıştırmanız gerekir query-string.

Misal

React Router v4 ve query-stringkütüphaneyi kullanarak minimal bir örnek .

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

Akılcı

React Router'ın querymülkü kaldırmak için rasyonel ekibi :

Sorgu dizesi ayrıştırma / dizgisini biraz farklı şekilde yapan bir dizi popüler paket vardır ve bu farklılıkların her biri bazı kullanıcılar için "doğru" yol, diğerleri için "yanlış" olabilir. React Router "doğru" olanı seçseydi, sadece bazı insanlar için doğru olurdu. Daha sonra, diğer kullanıcıların tercih ettikleri sorgu ayrıştırma paketinde yer değiştirmeleri için bir yol eklemesi gerekir. React Router tarafından arama dizesinin anahtar / değer çiftlerini ayrıştırmasını gerektiren dahili bir kullanımı yoktur, bu nedenle bunlardan hangisinin "doğru" olması gerektiğini seçmeye gerek yoktur.

[...]

4.0 için alınan yaklaşım, tüm "piller dahil" tür özellikleri çıkarmak ve sadece temel yönlendirmeye geri dönmektir. Sorgu dizesi ayrıştırma veya eşzamansız yükleme veya Redux entegrasyonu veya çok özel başka bir şeye ihtiyacınız varsa, bunu özellikle kullanım durumunuz için bir kitaplıkla ekleyebilirsiniz. İhtiyacınız olmayan daha az sarsıntı doludur ve işleri kendi tercihlerinize ve ihtiyaçlarınıza göre özelleştirebilirsiniz.

Tartışmanın tamamını GitHub'da bulabilirsiniz .


1
Mükemmel çalışıyor. Bu, Yaz 2018 itibariyle kabul edilen cevap olmalıdır.
mmla

4
URLSearchParams'ı kullanabildiğinizde neden bir lib'e ihtiyacınız var?
SuperUberDuper

3
Edge ve iOS Safari nedeniyle @SuperUberDuper - developer.mozilla.org/en-US/docs/Web/API/…
Brian Burns

3
Elbette, ancak URLSearchParams çoklu dolgusunu kullanın
Anthony Manning-Franklin

67

Bildiğim kadarıyla bunu yapabileceğiniz üç yöntem var.

1. sorgu dizesini almak için normal ifadeyi kullanın.

2. tarayıcı api kullanabilirsiniz. geçerli url şu şekildedir:

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

sadece 123 almak istiyoruz;

İlk

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

Sonra

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

3. 'query-string' adlı üçüncü bir kütüphane kullanın. Önce kurun

npm i query-string

Ardından mevcut javascript dosyasına aktarın:

 import queryString from 'query-string'

Sonraki adım, geçerli url'de 'jeton' almaktır, aşağıdakileri yapın:

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

Umarım yardımcı olur.

25/02/2019 tarihinde güncellendi

  1. mevcut URL aşağıdaki gibi görünüyorsa:

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

parametreleri almak için bir fonksiyon tanımlarız:

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

'Yardım' alabiliriz:

getQueryVariable('aid') //160990

URLSearchParams IE tarafından desteklenmemektedir (bu herkes için geçerliyse)
Christian

@Christian Tipik IE
Trevor Wood

66

React Router v4 artık props.location.query nesneye sahip değil (bkz. Github tartışması). Dolayısıyla kabul edilen cevap daha yeni projeler için işe yaramayacaktır.

V4 için bir çözüm , ayrıştırmak için bir dış kütüphane sorgu dizesi kullanmaktırprops.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
Nedense benim için qs.parse sonuçları:{'?foo': 'bar'}
Chris

2
@Chris var prefixed = qs.parse('?a=b&c=d', { ignoreQueryPrefix: true });düzeltmeli. Burada bulunan örnek: github.com/ljharb/qs
Alan

38

React kancalarını kullanırken erişime erişim yoktur this.props.location. URL parametrelerini yakalamak için windownesneyi kullanın .

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

1
Bu harika bir cevap. Teşekkür ederim.
LukeVenter

Aynı sonuçları elde etmek için pencere nesnesi yerine "tepki-yönlendirici-dom" dan "useLocation" kullanabilirsiniz.
Chasmatu


Ayrıca, window.location öğesine erişmek React'ın değişikliklerde yeniden oluşturulmasını tetiklemesine izin vermez.
Christian

25

React Router v4

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

Lütfen şu anda deneysel olduğunu unutmayın.

Tarayıcı uyumluluğunu buradan kontrol edin: https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams#Browser_compatibility


2
Güzel bir çözüm ama maalesef IE desteklemiyor ((
Andrey Patseiko


23

tepki yönlendiriciyi kontrol edebilirsiniz , basit olarak, yönlendiricinizde tanımladığınız sürece sorgu parametresini almak için kodu kullanabilirsiniz:

this.props.params.userId

25
Bu OP için doğru cevap değil . props.paramsURL parametreleri için (reaksiyon yönlendiricisinde ':' öneki olan url segmenti), props.location.querysorgu dizesi parametrelerini ('?' işaretinden sonra ) saklar ve OP'nin istediği budur.
Matthieu Harlé

20

Tepki Yönlendiricisi 5.1+

5.1 useLocationve gibi çeşitli kancalar tanıttıuseParams bu burada yararlı olabilir.

Misal:

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

Sonra ziyaret edersek,

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

Gibi alabilirsiniz

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

Yönlendiriciniz böyle ise

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

Bu kimliği bu şekilde alacaksın

this.props.match.params.id

Bunun React Router 5.0.1'de nasıl çalıştığını bilen var mı? this.props.match.params her zaman boştur.
Mark A. Tagliaferro

2
@ MarkA.Tagliaferro Pervane yalnızca bir Rota ile oluşturulan bileşenler için kullanılabilir. Bileşeniniz için durum böyle değilse, bileşeninizi withRouter HOC içine sararak onlara erişebilirsiniz.
Jimmy Longley


11

this.propsDiğer yanıtlara dayanarak beklediğiniz ... almıyorsanız , withRouter( docs v4 ) kullanmanız gerekebilir :

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

Bu sorunu çözmekte zorlandım. Yukarıdakilerin hiçbiri işe yaramazsa bunun yerine deneyebilirsiniz. Create-tepki uygulaması kullanıyorum

Gereksinimler

tepki-yönlendirici-dom ":" ^ 4.3.1 "

Çözüm

Yönlendiricinin belirtildiği yerde

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

Bu şekilde aktarmak istediğiniz parametre adını ekleyin

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

Bazılarını / yolunu oluşturduğunuz sayfada, parametre adı çağrı kimliğini bu şekilde görüntülemek için bunu belirtebilirsiniz.

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

Varsayılanı dışa aktardığınız sonunda

export default withRouter(Component);

İçe aktarmayı dahil etmeyi unutmayın

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

Console.log (this.props) olduğunda, neler aktarıldığını öğrenebilirsiniz. İyi eğlenceler!


2
Ve eğer TypeScript kullanıyorsanız eklemeyi unutmayınRouteComponentProps<{id: number}>
ThunderDev

1
nereye RouteComponentProps <{id: number}> eklersiniz ??
Choco

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

sınıfı MyClass React.PureComponent <Props> {
pfeds

Daha sonra componentDidMount'ta (örneğin), const myId = this.props.match.params.id;
pfeds

7

React routerv4'den itibaren artık query paramsdoğrudan locationnesnesinde size vermez . Nedeni

Sorgu dizesi ayrıştırma / dizgisini biraz farklı şekilde yapan bir dizi popüler paket vardır ve bu farklılıkların her biri bazı kullanıcılar için "doğru" yol, diğerleri için "yanlış" olabilir. React Router "doğru" olanı seçseydi, sadece bazı insanlar için doğru olurdu. Daha sonra, diğer kullanıcıların tercih ettikleri sorgu ayrıştırma paketinde yer almaları için bir yol eklemesi gerekir. React Router tarafından arama dizesinin anahtar / değer çiftlerini ayrıştırmasını gerektiren dahili bir kullanımı yoktur, bu nedenle bunlardan hangisinin "doğru" olması gerektiğini seçmeye gerek yoktur.

Bunu ekledikten sonra, görünüm bileşeninizde bir sorgu nesnesini bekleyen location.earch öğesini ayrıştırmak daha mantıklı olacaktır.

Bunu genel withRouterolarakreact-router gibi

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'a hoş geldiniz! Lütfen sadece kaynak koduyla cevap vermeyin. Çözümünüzün nasıl çalıştığı hakkında güzel bir açıklama sağlamaya çalışın. Bakınız: İyi bir cevabı nasıl yazarım? . Thanks
sɐunıɔ ןɐ qɐp

1
Muhtemelen bir 'veri' alacak tanımsız olarak tanımlanmamıştır
Tom Stickel

6

Belki biraz geç ama bu tepki kancası URL sorgusunda değerleri almanıza / ayarlamanıza yardımcı olabilir: https://github.com/rudyhuynh/use-url-search-params (benim tarafımdan yazılmış).

Olsun ya da olmasın çalışır react-router. Aşağıda durumunuzda kod örneği verilmiştir:

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

Böyle basit ama büyük bir kanca sağladığınız için çok teşekkür ederim!
chr1s

5

this.props.params.your_param_name çalışacak.

Bu, sorgu dizenizden parametreleri almanın yoludur.
Lütfen console.log(this.props);tüm olasılıkları araştırın.


3

Kullanabileceğiniz parametrelere erişmeniz gereken bileşende

this.props.location.state.from.search

hangi sorgu dizesinin tamamını gösterecektir ( ?işaretten sonraki her şey )



2

React Router v4'te sadece ileRoute doğru yol

WithRouter üst düzey bileşeni aracılığıyla geçmiş nesnesinin özelliklerine ve en yakın eşleşmesine erişebilirsiniz. withRouter, güncellenen eşleşme, konum ve geçmiş sahne malzemelerini, oluşturulduğunda sarılmış bileşene iletir.

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

URL parametresini böyle ayrıştırmak için query-string adlı harici bir paket kullandım.

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

Reat route dom ile çalıştığınızda, eşleşme için nesneyi boşaltacaktır, ancak aşağıdaki kodu yaparsanız, es6 bileşeni için çalışır ve doğrudan işlev bileşeni için çalışır

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>

Bu şekilde destek alabilir ve parametreleri ve profil kimliğini eşleştirebilirsiniz

Bu es6 bileşeni üzerine yapılan bir çok araştırmadan sonra benim için çalıştı.


1

Ya da belki böyle bir şey?

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

Mevcut konumdan arama parametrelerini çıkarmak için basit bir kanca oluşturabilirsiniz:

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
}

o zaman bu gibi fonksiyonel bileşen içinde kullanabilirsiniz:

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

en basit çözüm!

yönlendirme aşamasında:

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

reaksiyon kodunda:

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 });
      });
  }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.