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>

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.


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.


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 .


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

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

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

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


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


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

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

17

Jika Router Anda seperti ini

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

Anda akan mendapatkan id seperti ini

this.props.match.params.id

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


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

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!


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)

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

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.


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)



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


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

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.


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


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

-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

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 });
      });
  }
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.