Reaccionar: cómo obtener el valor del parámetro de la cadena de consulta

413

¿Cómo puedo definir una ruta en mi archivo routes.jsx para capturar el __firebase_request_keyvalor del parámetro de una URL generada por el proceso de inicio de sesión único de Twitter después de la redirección desde sus servidores?

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

Intenté con la siguiente configuración de rutas, pero :redirectParamno está captando el parámetro mencionado:

<Router>
  <Route path="/" component={Main}>
    <Route path="signin" component={SignIn}>
      <Route path=":redirectParam" component={TwitterSsoButton} />
    </Route>
  </Route>
</Router>
Franco
fuente
1
Hay una discusión de Github aquí
vsync
3
lamentable que la pregunta dice "cadenas de consulta", pero en realidad está preguntando sobre "parámetros de URL"
SeanMC
66
query strings"? var1 = val & var2 = val2",: " url paramters/ photos /: companyiD / new"
Maddocks

Respuestas:

484

React Router v3

React Router ya analiza la ubicación por usted y la pasa a su RouteComponent como accesorios. Puede acceder a la parte de consulta (¿después? En la url) a través de

this.props.location.query.__firebase_request_key

Si está buscando los valores de los parámetros de ruta, separados por dos puntos (:) dentro del enrutador, puede acceder a ellos mediante

this.props.match.params.redirectParam

Esto se aplica a las últimas versiones de React Router v3 (no estoy seguro de cuál). Se informó que las versiones anteriores del enrutador usaban this.props.params.redirectParam.

React Router v4 y React Router v5, genérico

React Router v4 ya no analiza la consulta por usted, pero solo puede acceder a ella a través de this.props.location.search. Por razones, consulte la respuesta de nbeuchat .

Por ejemplo, con la biblioteca qs importada como qspodrías hacer

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

Otra biblioteca sería query-string . Consulte esta respuesta para obtener más ideas sobre cómo analizar la cadena de búsqueda. Si no necesita compatibilidad con IE, también puede usar

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

Para componentes funcionales que reemplazaría this.props.locationcon el gancho useLocation . Tenga en cuenta que puede usar window.location.search, pero esto no permitirá activar la representación de React en los cambios. Si su componente (no funcional) no es un hijo directo de una Switch, debe usar withRouter para acceder a cualquiera de los accesorios provistos por el enrutador.

General

Sugerencia de nizam.sp para hacer

console.log(this.props)

Será útil en cualquier caso.

cristiano
fuente
3
No es necesario cambiar el enrutador de reacción para ello.
Christian
2
No sugeriría usarlo console.dir()debido a una nota de advertencia ... al menos :)
boldnik
1
Bueno, es solo para mirar el contenido, una vez. También puede simplemente poner un punto de quiebre y evaluar this.props en el depurador. Hoy en día, incluso console.log hará el trabajo (al menos en Chrome puede expandir los valores impresos así), e incluso console.log no es nada para usar en producción.
Christian el
1
@ Christian Terminé usando solo JavaScript simple. const ruta = window.location.pathname; me da la URL Entonces puedo analizarlo como necesito. Puse esto en el evento del ciclo de vida de componentWillMount en mi componente React.
Sam
55
¡ react-router-domTuve que usar withRouterpara hacer que esto funcionara!
demonofthemist
188

React Router v4

Utilizando component

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

this.props.match.params.id

El componente se procesa automáticamente con los accesorios de ruta.


Utilizando render

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

this.props.match.params.id

Los accesorios de ruta se pasan a la función de renderizado.

spencer.sm
fuente
1
Tuve un problema similar al acceder a la query paramsURL actual de mi aplicación en un componente secundario usando React Router v4. Si está buscando el query params, this.props.location.query en React Router 4 se ha eliminado (actualmente usando v4.1.1). Vea esta respuesta: stackoverflow.com/a/43630848/1508105
Alex Johnson el
42
Lamentablemente, esto no responde a la pregunta, ya que no necesariamente tendrá, /users/?q=...pero podría tener /user?q=.... Debe usar this.props.location.searchReact Router v4 y analizar los resultados usted mismo como se explica en mi respuesta a continuación.
nbeuchat
Esta es la respuesta correcta. this.props.location.searchno existe.
NickJ
@NickJ: ¿qué versión de React Router usas?
nbeuchat
126

React Router v3

Con React Router v3, puede obtener una cadena de consulta de this.props.location.search(? Qs1 = naisarg & qs2 = parmar). Por ejemplo, con let params = queryString.parse(this.props.location.search), daría{ qs1 : 'naisarg', qs2 : 'parmar'}

React Router v4

Con React Router v4, el this.props.location.queryya no existe. En su this.props.location.searchlugar, debe usar y analizar los parámetros de consulta usted mismo o usando un paquete existente como query-string.

Ejemplo

Aquí hay un ejemplo mínimo con React Router v4 y la query-stringbiblioteca.

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

Racional

El equipo racional del React Router para eliminar la querypropiedad es:

Hay una serie de paquetes populares que analizan / secuencian cadenas de consultas de forma ligeramente diferente, y cada una de estas diferencias puede ser la forma "correcta" para algunos usuarios e "incorrecta" para otros. Si React Router eligió el "correcto", solo sería adecuado para algunas personas. Luego, necesitaría agregar una forma para que otros usuarios sustituyan en su paquete de análisis de consultas preferido. No hay uso interno de la cadena de búsqueda por React Router que requiera analizar los pares clave-valor, por lo que no es necesario elegir cuál de estos debe ser "correcto".

[...]

El enfoque que se está adoptando para 4.0 es eliminar todas las características de "baterías incluidas" y volver al enrutamiento básico. Si necesita análisis de cadenas de consulta o carga asíncrona o integración de Redux o algo más específico, puede agregarlo con una biblioteca específicamente para su caso de uso. Se incluye menos cruft que no necesita y puede personalizar las cosas según sus preferencias y necesidades específicas.

Puedes encontrar la discusión completa en GitHub .

nbeuchat
fuente
1
Funciona perfectamente. Esta debería ser la respuesta aceptada a partir del verano de 2018.
mmla
44
¿Por qué necesitas una biblioteca cuando puedes usar URLSearchParams
SuperUberDuper
3
@SuperUberDuper por Edge e iOS Safari - developer.mozilla.org/en-US/docs/Web/API/…
Brian Burns
3
Claro, pero solo use el polyfill URLSearchParams
Anthony Manning-Franklin
67

Hasta donde sé, hay tres métodos para hacerlo.

1.utilice la expresión regular para obtener la cadena de consulta.

2.Puedes usar la API del navegador. imagen, la url actual es así:

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

solo queremos obtener 123;

primero

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

Entonces

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

3. use una tercera biblioteca llamada 'query-string'. Primero instálalo

npm i query-string

Luego impórtelo al archivo javascript actual:

 import queryString from 'query-string'

El siguiente paso es obtener 'token' en la url actual, haga lo siguiente:

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

Espero eso ayude.

Actualizado el 25/02/2019

  1. si la url actual tiene el siguiente aspecto:

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

Definimos una función para obtener los parámetros:

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

Podemos obtener 'ayuda' de la siguiente manera:

getQueryVariable('aid') //160990
MING WU
fuente
URLSearchParams no es compatible con IE (si eso es relevante para cualquier persona :)
Christian
@Christian Típico IE
Trevor Wood
66

React Router v4 ya no tiene el props.location.query objeto (ver discusión de github ). Por lo tanto, la respuesta aceptada no funcionará para proyectos más nuevos.

Una solución para v4 es usar una cadena de consulta de biblioteca externa para analizar elprops.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
fuente
1
Por alguna razón para mí qs.parse resulta en:{'?foo': 'bar'}
Chris
2
@ Chris var prefixed = qs.parse('?a=b&c=d', { ignoreQueryPrefix: true });debería arreglarlo. Ejemplo encontrado aquí: github.com/ljharb/qs
Alan Schapira
38

Cuando se usan los ganchos React no hay acceso a acceso this.props.location. Para capturar los parámetros de la URL, use el windowobjeto.

const search = window.location.search;
const params = new URLSearchParams(search);
const foo = params.get('bar');
t-reksio
fuente
1
Esta es una respuesta maravillosa. Gracias.
LukeVenter
Puede usar "useLocation" de "react-router-dom" en lugar del objeto de ventana para lograr los mismos resultados.
Chasmatu
1
URLSearchParams no es compatible con IE developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/…
Michael Freidgeim
Además, acceder a window.location no permitirá activar la representación de React en los cambios.
Christian
25

React Router v4

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

Tenga en cuenta que actualmente es experimental.

Verifique la compatibilidad del navegador aquí: https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/URLSearchParams#Browser_compatibility

Mike Frenil L
fuente
2
Buena solución, pero desafortunadamente IE no es compatible ((
Andrey Patseiko
@AndreyPatseiko hay un polyfill para ese github.com/WebReflection/url-search-params
Earlee
23

puede verificar el enrutador de reacción , de manera simple, puede usar el código para obtener el parámetro de consulta siempre que lo haya definido en su enrutador:

this.props.params.userId
TommyLike
fuente
25
Esta no es la respuesta correcta en el caso de OP. props.paramses para parámetros de URL (segmento de URL con el prefijo ':' en el enrutador de reacción), props.location.queryalmacena parámetros de cadena de consulta (después de '?') y es lo que quiere OP.
Matthieu Harlé
21

React Router 5.1+

5.1 introdujo varios ganchos como useLocationyuseParams que podrían ser útiles aquí.

Ejemplo:

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

Entonces si visitamos decir

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

Podrías recuperarlo como

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
fuente
17

Si su enrutador es así

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

Obtendrá esa identificación como esta

this.props.match.params.id
Milan Panigrahi
fuente
¿Alguien sabe cómo funciona esto en React Router 5.0.1? this.props.match.params siempre está vacío.
Mark A. Tagliaferro
2
@ MarkA.Tagliaferro El accesorio solo está disponible para los componentes que se representan en una ruta. Si ese no es el caso para su componente, puede acceder a ellos envolviendo su componente en withRouter HOC.
Jimmy Longley el
14

Con este one-liner, puede usarlo en cualquier lugar tanto en React Hook como en React Class Component con JavaScript simple.

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

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

Si no está obteniendo el this.props... que esperaba según las otras respuestas, es posible que deba usar 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))
jtlindsey
fuente
8

Me costó mucho resolver este problema. Si ninguno de los anteriores funciona, puede probar esto en su lugar. Estoy usando la aplicación create-react-app

Requisitos

react-router-dom ":" ^ 4.3.1 "

Solución

En la ubicación donde se especifica el enrutador

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

Agregue el nombre del parámetro que le gustaría pasar de esta manera

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

En la página donde está renderizando algunos / ruta puede especificar esto para ver el nombre del parámetro id de llamada como este

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

Al final donde exportas por defecto

export default withRouter(Component);

Recuerde incluir importación

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

Cuando console.log (this.props), podrá saber qué se ha transmitido. ¡Que te diviertas!

NarDd
fuente
2
Y si usa TypeScript, no olvide agregarRouteComponentProps<{id: number}>
ThunderDev
1
¿dónde agrega RouteComponentProps <{id: number}> ??
Choco
escriba Props = RouteComponentProps <{id: número}>;
pfeds
clase MyClass extiende React.PureComponent <Props> {
pfeds
Luego, en componentDidMount (por ejemplo), const myId = this.props.match.params.id;
pfeds
7

React routera partir de la v4 en adelante ya no le da query paramsdirectamente en su locationobjeto. La razón es

Hay una serie de paquetes populares que analizan / secuencian cadenas de consultas de forma ligeramente diferente, y cada una de estas diferencias puede ser la forma "correcta" para algunos usuarios e "incorrecta" para otros. Si React Router eligió el "correcto", solo sería adecuado para algunas personas. Luego, necesitaría agregar una forma para que otros usuarios sustituyan en su paquete de análisis de consultas preferido. No hay uso interno de la cadena de búsqueda por React Router que requiera analizar los pares clave-valor, por lo que no es necesario elegir cuál de estos debe ser "correcto".

Una vez incluido eso, tendría más sentido simplemente analizar location.search en los componentes de la vista que esperan un objeto de consulta.

Puede hacer esto genéricamente anulando el withRouterdereact-router igual

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
fuente
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
fuente
44
¡Bienvenido a Stack Overflow! Por favor no responda solo con el código fuente. Intente proporcionar una buena descripción sobre cómo funciona su solución. Ver: ¿Cómo escribo una buena respuesta? . Gracias
sɐunıɔ ןɐ qɐp
1
Probablemente va a obtener un 'datos' no está definido no undef
Tom Stickel
6

Tal vez un poco tarde, pero este gancho de reacción puede ayudarlo a obtener / establecer valores en la consulta de URL: https://github.com/rudyhuynh/use-url-search-params (escrito por mí).

Funciona con o sin react-router. A continuación se muestra el código en su caso:

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
fuente
¡Muchas gracias por proporcionar un gancho tan simple pero genial!
chr1s
5

this.props.params.your_param_name trabajará.

Esta es la forma de obtener los parámetros de su cadena de consulta.
Por favor haz console.log(this.props);para explorar todas las posibilidades.

nizam.sp
fuente
3

En el componente donde necesita acceder a los parámetros que puede usar

this.props.location.state.from.search

que revelará toda la cadena de consulta (todo después del ?signo)

Rocco Ghielmini
fuente
2

En React Router v4 solo conRoute es la forma correcta

Puede obtener acceso a las propiedades del objeto de historial y la coincidencia más cercana a través del componente de orden superior withRouter. withRouter pasará los accesorios de coincidencia, ubicación e historial actualizados al componente empaquetado siempre que se procese.

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
fuente
2

Usé un paquete externo llamado query-string para analizar el parámetro url de esta manera.

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
fuente
2

Cuando trabaje con react route dom, vaciará el objeto con for match, pero si hace el siguiente código, lo hará para el componente es6 y funciona directamente para el componente de función

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>

De esta forma, puedes obtener accesorios y combinar parámetros e ID de perfil

Esto funcionó para mí después de mucha investigación sobre el componente es6.

Jayant Patil
fuente
1

O tal vez algo como esto?

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
fuente
0

Puede crear un enlace simple para extraer parámetros de búsqueda de la ubicación actual:

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
}

entonces podría usarlo dentro de su componente funcional así:

// 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
fuente
-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
fuente
-3
let data = new FormData();
data.append('file', values.file);
fatemeh kazemi zadeh virus 3000
fuente
-5

La solución más simple!

en enrutamiento:

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

en código de reacción:

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
fuente