React - Cara mendapatkan nilai parameter dari string kueri

412

Bagaimana saya bisa mendefinisikan rute dalam file routes.jsx saya untuk menangkap nilai __firebase_request_keyparameter dari URL yang dihasilkan oleh proses masuk tunggal Twitter setelah pengalihan dari server mereka?

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

Saya mencoba dengan konfigurasi rute berikut, tetapi :redirectParamtidak menangkap param yang disebutkan:

<Router>
  <Route path="/" component={Main}>
    <Route path="signin" component={SignIn}>
      <Route path=":redirectParam" component={TwitterSsoButton} />
    </Route>
  </Route>
</Router>
Franco
sumber
1
Ada diskusi Github di sini
vsync
3
disayangkan bahwa pertanyaannya mengatakan "string permintaan" tetapi sebenarnya bertanya tentang "parameter url"
SeanMC
6
query strings"? var1 = val & var2 = val2",: url paramters"/ photos /: companyiD / new"
Maddocks

Jawaban:

484

Bereaksi Router v3

React Router sudah mem-parsing lokasi untuk Anda dan meneruskannya ke RouteComponent Anda sebagai alat peraga. Anda dapat mengakses bagian permintaan (setelah? Di url) melalui

this.props.location.query.__firebase_request_key

Jika Anda mencari nilai parameter path, dipisahkan dengan titik dua (:) di dalam router, ini dapat diakses melalui

this.props.match.params.redirectParam

Ini berlaku untuk versi React Router v3 yang terlambat (tidak yakin yang mana). Versi router yang lebih lama dilaporkan digunakanthis.props.params.redirectParam .

React Router v4 dan React Router v5, generik

React Router v4 tidak menguraikan kueri untuk Anda lagi, tetapi Anda hanya dapat mengaksesnya melalui this.props.location.search. Untuk alasan, lihat jawaban nbeuchat .

Misalnya dengan pustaka qs yang diimpor sebanyak yang qsAnda bisa lakukan

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

Pustaka lain adalah string-query . Lihat jawaban ini untuk beberapa ide lagi tentang penguraian string pencarian. Jika Anda tidak memerlukan kompatibilitas IE, Anda juga dapat menggunakannya

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

Untuk komponen fungsional, Anda akan mengganti this.props.locationdengan hook useLocation . Catatan, Anda dapat menggunakan window.location.search, tetapi ini tidak akan memungkinkan untuk memicu React rendering on changes. Jika komponen (non-fungsional) Anda bukan anak langsung dari SwitchAnda perlu menggunakan withRouter untuk mengakses alat peraga yang disediakan router.

Umum

saran nizam.sp untuk dilakukan

console.log(this.props)

akan membantu dalam hal apa pun.

Kristen
sumber
3
Tidak perlu mengubah router reaksi untuk itu.
Christian
2
Saya tidak akan menyarankan menggunakan console.dir()karena catatan peringatan ... setidaknya :)
boldnik
1
Yah, itu hanya untuk melihat isinya, sekali saja. Anda juga bisa meletakkan break point dan mengevaluasi this.props di debugger. Saat ini, bahkan console.log akan melakukan pekerjaannya (setidaknya di Chrome Anda dapat memperluas nilai yang dicetak seperti itu) - dan bahkan console.log tidak dapat digunakan dalam produksi.
Christian
1
@Christian Saya akhirnya menggunakan javascript biasa. const path = window.location.pathname; beri saya URL. Saya kemudian dapat menguraikannya dengan cara yang saya butuhkan. Saya menempatkan ini di event siklus hidup componentWillMount di komponen React saya.
Sam
5
Dalam react-router-domAku harus menggunakan withRouteruntuk membuat pekerjaan ini!
demonofthemist
188

Bereaksi Router v4

Menggunakan component

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

this.props.match.params.id

Komponen secara otomatis diberikan dengan alat peraga rute.


Menggunakan render

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

this.props.match.params.id

Alat peraga rute diteruskan ke fungsi render.

spencer.sm
sumber
1
Saya memiliki masalah serupa dalam mengakses query paramsURL aplikasi saya saat ini di komponen turunan menggunakan React Router v4. Jika Anda mencari query params, this.props.location.query di React Router 4 telah dihapus (saat ini menggunakan v4.1.1). Lihat jawaban ini: stackoverflow.com/a/43630848/1508105
Alex Johnson
42
Sayangnya ini tidak menjawab pertanyaan karena Anda belum tentu memiliki /users/?q=...tetapi Anda bisa melakukannya /user?q=.... Anda harus menggunakan this.props.location.searchReact Router v4 dan mengurai hasilnya sendiri seperti yang dijelaskan dalam jawaban saya di bawah ini.
nbeuchat
Ini jawaban yang benar. this.props.location.searchtidak ada.
NickJ
@NickJ: versi React Router yang Anda gunakan?
nbeuchat
126

Bereaksi Router v3

Dengan React Router v3, Anda bisa mendapatkan kueri-string dari this.props.location.search(? Qs1 = naisarg & qs2 = parmar). Misalnya, dengan let params = queryString.parse(this.props.location.search), mau memberi{ qs1 : 'naisarg', qs2 : 'parmar'}

Bereaksi Router v4

Dengan React Router v4, this.props.location.querytidak ada lagi. Anda perlu menggunakan this.props.location.searchdan mengurai parameter kueri sendiri atau menggunakan paket yang ada sepertiquery-string .

Contoh

Berikut adalah contoh minimal menggunakan React Router v4 dan query-stringperpustakaan.

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

Rasional

Rasional tim React Router untuk menghapus queryproperti adalah:

Ada sejumlah paket populer yang melakukan penguraian string / pengurutan string yang sedikit berbeda, dan masing-masing perbedaan ini mungkin merupakan cara "benar" untuk beberapa pengguna dan "salah" untuk yang lain. Jika React Router memilih yang "benar", itu hanya akan tepat untuk beberapa orang. Kemudian, perlu menambahkan cara bagi pengguna lain untuk mengganti dalam paket penguraian kueri yang mereka inginkan. Tidak ada penggunaan internal string pencarian oleh React Router yang mengharuskannya untuk menguraikan pasangan nilai kunci, sehingga tidak perlu memilih yang mana yang harus "benar".

[...]

Pendekatan yang diambil untuk 4.0 adalah menghapus semua jenis "baterai yang disertakan" dan kembali ke perutean dasar saja. Jika Anda memerlukan penguraian string kueri atau pemuatan async atau integrasi Redux atau hal lain yang sangat spesifik, maka Anda dapat menambahkannya dengan pustaka khusus untuk kasus penggunaan Anda. Less cruft dikemas dalam hal yang tidak Anda butuhkan dan Anda dapat menyesuaikan hal-hal dengan preferensi dan kebutuhan spesifik Anda.

Anda dapat menemukan diskusi lengkap tentang GitHub .

nbeuchat
sumber
1
Bekerja dengan sempurna. Ini harus menjadi jawaban yang diterima pada Musim Panas 2018.
mmla
4
mengapa Anda bahkan memerlukan lib ketika Anda dapat menggunakan URLSearchParams
SuperUberDuper
3
@SuperUberDuper karena Edge dan iOS Safari - developer.mozilla.org/en-US/docs/Web/API/…
Brian Burns
3
Tentu, tetapi kemudian gunakan polyfill URLSearchParams
Anthony Manning-Franklin
67

Sejauh yang saya tahu ada tiga metode yang dapat Anda lakukan itu.

1. gunakan ekspresi reguler untuk mendapatkan string kueri.

2. Anda dapat menggunakan api browser. gambar url saat ini adalah seperti ini:

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

kami hanya ingin mendapatkan 123;

Pertama

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

Kemudian

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

3. gunakan perpustakaan ketiga yang disebut 'query-string'. Pertama instal

npm i query-string

Kemudian impor ke file javascript saat ini:

 import queryString from 'query-string'

Langkah selanjutnya adalah mendapatkan 'token' di url saat ini, lakukan hal berikut:

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

Semoga ini bisa membantu.

Diperbarui pada 25/02/2019

  1. jika url saat ini terlihat seperti berikut:

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

kami mendefinisikan fungsi untuk mendapatkan parameter:

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

Kami bisa mendapatkan 'bantuan' dengan:

getQueryVariable('aid') //160990
MING WU
sumber
URLSearchParams tidak didukung oleh IE (jika itu relevan bagi siapa pun :)
Christian
@Christian Typical IE
Trevor Wood
66

React Router v4 tidak lagi memiliki props.location.query objek (lihat diskusi github ). Jadi jawaban yang diterima tidak akan berfungsi untuk proyek yang lebih baru.

Solusi untuk v4 adalah menggunakan string-string pustaka luar untuk menguraikanprops.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'}
JTG
sumber
1
Untuk beberapa alasan bagi saya qs.parse menghasilkan:{'?foo': 'bar'}
Chris
2
@ Chris var prefixed = qs.parse('?a=b&c=d', { ignoreQueryPrefix: true });harus memperbaikinya. Contoh ditemukan di sini: github.com/ljharb/qs
Alan Schapira
38

Saat menggunakan React hooks tidak ada akses untuk mengakses this.props.location. Untuk mengambil parameter url gunakan windowobjek.

const search = window.location.search;
const params = new URLSearchParams(search);
const foo = params.get('bar');
t-reksio
sumber
1
Ini jawaban yang bagus. Terima kasih.
LukeVenter
Anda dapat menggunakan "useLocation" dari "react-router-dom" sebagai ganti objek window untuk mencapai hasil yang sama.
Chasmatu
1
URLSearchParams Tidak didukung oleh IE developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/…
Michael Freidgeim
Selain itu, mengakses window.location tidak akan memungkinkan untuk memicu re-render pada perubahan.
Christian
25

Bereaksi Router v4

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

Harap dicatat bahwa ini sedang dalam percobaan.

Periksa kompatibilitas browser di sini: https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams#Browser_compatibility

Mike Frenil L
sumber
2
Solusi yang bagus tapi sayangnya IE tidak mendukung ((
Andrey Patseiko
@AndreyPatseiko ada polyfill untuk github.com/WebReflection/url-search-params
Earlee
23

Anda dapat memeriksa react-router , secara sederhana, Anda dapat menggunakan kode untuk mendapatkan parameter kueri selama Anda mendefinisikan di router Anda:

this.props.params.userId
TommyLike
sumber
25
Ini bukan jawaban yang tepat dalam kasus OP. props.paramsadalah untuk URL params (segmen url diawali dengan ':' di router reaksi), props.location.querymenyimpan parameter string permintaan (setelah '?') dan itulah yang diinginkan OP.
Matthieu Harlé
21

Bereaksi Router 5.1+

5.1 memperkenalkan berbagai kait seperti useLocationdanuseParams yang bisa digunakan di sini.

Contoh:

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

Lalu kalau kita berkunjung katakanlah

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

Anda bisa mengambilnya seperti

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>;
}
dsgriffin
sumber
17

Jika Router Anda seperti ini

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

Anda akan mendapatkan id seperti ini

this.props.match.params.id
Milan Panigrahi
sumber
Adakah yang tahu cara kerjanya di React Router 5.0.1? this.props.match.params selalu kosong.
Mark A. Tagliaferro
2
@ MarkA.Tagliaferro Prop hanya dapat digunakan untuk komponen yang dirender oleh Rute. Jika itu bukan kasus untuk komponen Anda, Anda dapat mengaksesnya dengan membungkus komponen Anda di withRouter HOC.
Jimmy Longley
14

Dengan one-liner ini, Anda dapat menggunakannya di mana saja di React Hook dan React Class Component dengan JavaScript biasa.

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

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

Jika Anda tidak mendapatkan this.props... yang Anda harapkan berdasarkan jawaban yang lain, Anda mungkin perlu menggunakan 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))
jindlindsey
sumber
8

Saya kesulitan menyelesaikan masalah ini. Jika tidak ada yang berhasil Anda dapat mencoba ini. Saya menggunakan aplikasi create-react-app

Persyaratan

react-router-dom ":" ^ 4.3.1 "

Larutan

Di lokasi di mana router ditentukan

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

Tambahkan nama parameter yang ingin Anda sampaikan seperti ini

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

Pada halaman tempat Anda merender beberapa / jalur, Anda dapat menentukan ini untuk melihat id panggilan nama parameter seperti ini

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

Di akhir di mana Anda mengekspor default

export default withRouter(Component);

Ingatlah untuk memasukkan impor

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

Ketika console.log (this.props) Anda akan dapat apa yang telah diturunkan. Selamat bersenang-senang!

NarDd
sumber
2
Dan jika menggunakan TypeScript jangan lupa untuk menambahkanRouteComponentProps<{id: number}>
ThunderDev
1
di mana Anda menambahkan RouteComponentProps <{id: number}> ??
Choco
ketik Props = RouteComponentProps <{id: number}>;
pfeds
class MyClass memperluas React.PureComponent <Props> {
pfeds
Kemudian di componentDidMount (misalnya), const myId = this.props.match.params.id;
Bagasi
7

React routerdari v4 dan seterusnya tidak lagi memberi Anda query paramslangsung di locationobjeknya. Alasannya adalah

Ada sejumlah paket populer yang melakukan penguraian string / pengurutan string yang sedikit berbeda, dan masing-masing perbedaan ini mungkin merupakan cara "benar" untuk beberapa pengguna dan "salah" untuk yang lain. Jika React Router memilih yang "benar", itu hanya akan tepat untuk beberapa orang. Kemudian, perlu menambahkan cara bagi pengguna lain untuk mengganti dalam paket penguraian kueri yang mereka inginkan. Tidak ada penggunaan internal string pencarian oleh React Router yang mengharuskannya untuk menguraikan pasangan nilai kunci, sehingga tidak perlu memilih yang mana yang harus "benar".

Setelah memasukkan itu, akan lebih masuk akal untuk hanya mengurai location.search dalam komponen tampilan Anda yang mengharapkan objek permintaan.

Anda dapat melakukan ini secara umum dengan mengganti withRouterdarireact-router like

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)
Shubham Khatri
sumber
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
    })
}
Anas Alpure
sumber
4
Selamat Datang di Stack Overflow! Tolong jangan jawab hanya dengan kode sumber. Cobalah untuk memberikan deskripsi yang bagus tentang cara kerja solusi Anda. Lihat: Bagaimana saya menulis jawaban yang baik? . Terima kasih
sɐunıɔ ןɐ qɐp
1
Mungkin akan mendapatkan 'data' tidak didefinisikan tanpa-undef
Tom Stickel
6

Mungkin agak terlambat tetapi kaitan reaksi ini dapat membantu Anda mendapatkan / menetapkan nilai dalam permintaan URL: https://github.com/rudyhuynh/use-url-search-params (ditulis oleh saya).

Ini bekerja dengan atau tanpa react-router. Di bawah ini adalah contoh kode dalam kasus Anda:

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>
  )
}
Ruby Ybur
sumber
Terima kasih banyak telah menyediakan kait yang sederhana namun hebat!
chr1s
5

this.props.params.your_param_name akan bekerja.

Ini adalah cara untuk mendapatkan params dari string kueri Anda.
Silakan lakukan console.log(this.props);untuk mengeksplorasi semua kemungkinan.

nizam.sp
sumber
3

Di komponen tempat Anda perlu mengakses parameter yang dapat Anda gunakan

this.props.location.state.from.search

yang akan mengungkapkan seluruh string kueri (semuanya setelah ?tanda)

Rocco Ghielmini
sumber
2

Di Bereaksi Router v4 hanya withRoute adalah cara yang benar

Anda bisa mendapatkan akses ke properti objek sejarah dan kecocokan terdekat melalui komponen withRouter orde tinggi. withRouter akan meneruskan alat peraga pertandingan, lokasi, dan riwayat yang diperbarui ke komponen yang dibungkus setiap kali dirender.

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

krystianj
sumber
2

Saya menggunakan paket eksternal yang disebut query-string untuk mengurai parameter url seperti itu.

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}));
}
Joe
sumber
2

Ketika Anda bekerja dengan dom rute reaksi maka akan mengosongkan objek dengan untuk mencocokkan tetapi jika Anda melakukan kode berikut maka itu akan untuk komponen es6 serta bekerja langsung untuk komponen fungsi

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>

Dengan cara ini Anda bisa mendapatkan alat peraga dan mencocokkan params dan id profil

Ini bekerja untuk saya setelah banyak penelitian tentang komponen ES6.

Jayant Patil
sumber
1

Atau mungkin sesuatu seperti ini?

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

prabhu
sumber
0

Anda dapat membuat kait sederhana untuk mengekstraksi params pencarian dari lokasi saat ini:

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
}

maka Anda dapat menggunakannya di dalam komponen fungsional Anda seperti ini:

// 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'}
kajkal
sumber
-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}
        );
}
Roushan Jha
sumber
-3
let data = new FormData();
data.append('file', values.file);
fatemeh kazemi zadeh virus3000
sumber
-5

solusi paling sederhana!

dalam routing:

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

dalam kode reaksi:

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