Pase los accesorios en Link react-router

137

Estoy usando react con react-router. Estoy tratando de pasar propiedades en un "Enlace" de react-router

var React  = require('react');
var Router = require('react-router');
var CreateIdeaView = require('./components/createIdeaView.jsx');

var Link = Router.Link;
var Route = Router.Route;
var DefaultRoute = Router.DefaultRoute;
var RouteHandler = Router.RouteHandler;
var App = React.createClass({
  render : function(){
    return(
      <div>
        <Link to="ideas" params={{ testvalue: "hello" }}>Create Idea</Link>
        <RouteHandler/>
      </div>
    );
  }
});

var routes = (
  <Route name="app" path="/" handler={App}>
    <Route name="ideas" handler={CreateIdeaView} />
    <DefaultRoute handler={Home} />
  </Route>
);

Router.run(routes, function(Handler) {

  React.render(<Handler />, document.getElementById('main'))
});

El "Enlace" representa la página pero no pasa la propiedad a la nueva vista. A continuación se muestra el código de vista

var React = require('react');
var Router = require('react-router');

var CreateIdeaView = React.createClass({
  render : function(){
    console.log('props form link',this.props,this)//props not recived
  return(
      <div>
        <h1>Create Post: </h1>
        <input type='text' ref='newIdeaTitle' placeholder='title'></input>
        <input type='text' ref='newIdeaBody' placeholder='body'></input>
      </div>
    );
  }
});

module.exports = CreateIdeaView;

¿Cómo puedo pasar datos usando "Link"?

vishal atmakuri
fuente

Respuestas:

123

Falta esta línea path:

<Route name="ideas" handler={CreateIdeaView} />

Debiera ser:

<Route name="ideas" path="/:testvalue" handler={CreateIdeaView} />

Dado lo siguiente Link (v1 desactualizado) :

<Link to="ideas" params={{ testvalue: "hello" }}>Create Idea</Link>

Actualizado a partir de v4 :

const backUrl = '/some/other/value'
// this.props.testvalue === "hello"
<Link to={{pathname: `/${this.props.testvalue}`, query: {backUrl}}} />

y en los withRouter(CreateIdeaView)componentes render():

console.log(this.props.match.params.testvalue, this.props.location.query.backurl)
// output
hello /some/other/value

Desde el enlace que publicó en los documentos, hacia la parte inferior de la página:

Dada una ruta como <Route name="user" path="/users/:userId"/>



Ejemplo de código actualizado con algunos ejemplos de consulta con trozos:

// import React, {Component, Props, ReactDOM} from 'react';
// import {Route, Switch} from 'react-router'; etc etc
// this snippet has it all attached to window since its in browser
const {
  BrowserRouter,
  Switch,
  Route,
  Link,
  NavLink
} = ReactRouterDOM;

class World extends React.Component {
  constructor(props) {
    super(props);
    console.dir(props);      
    this.state = {
      fromIdeas: props.match.params.WORLD || 'unknown'
    }
  }
  render() {
    const { match, location} = this.props;
    return (
      <React.Fragment>
        <h2>{this.state.fromIdeas}</h2>
        <span>thing: 
          {location.query 
            && location.query.thing}
        </span><br/>
        <span>another1: 
        {location.query 
          && location.query.another1 
          || 'none for 2 or 3'}
        </span>
      </React.Fragment>
    );
  }
}

class Ideas extends React.Component {
  constructor(props) {
    super(props);
    console.dir(props);
    this.state = {
      fromAppItem: props.location.item,
      fromAppId: props.location.id,
      nextPage: 'world1',
      showWorld2: false
    }
  }
  render() {
    return (
      <React.Fragment>
          <li>item: {this.state.fromAppItem.okay}</li>
          <li>id: {this.state.fromAppId}</li>
          <li>
            <Link 
              to={{
                pathname: `/hello/${this.state.nextPage}`, 
                query:{thing: 'asdf', another1: 'stuff'}
              }}>
              Home 1
            </Link>
          </li>
          <li>
            <button 
              onClick={() => this.setState({
              nextPage: 'world2',
              showWorld2: true})}>
              switch  2
            </button>
          </li>
          {this.state.showWorld2 
           && 
           <li>
              <Link 
                to={{
                  pathname: `/hello/${this.state.nextPage}`, 
                  query:{thing: 'fdsa'}}} >
                Home 2
              </Link>
            </li> 
          }
        <NavLink to="/hello">Home 3</NavLink>
      </React.Fragment>
    );
  }
}


class App extends React.Component {
  render() {
    return (
      <React.Fragment>
        <Link to={{
          pathname:'/ideas/:id', 
          id: 222, 
          item: {
              okay: 123
          }}}>Ideas</Link>
        <Switch>
          <Route exact path='/ideas/:id/' component={Ideas}/>
          <Route path='/hello/:WORLD?/:thing?' component={World}/>
        </Switch>
      </React.Fragment>
    );
  }
}

ReactDOM.render((
  <BrowserRouter>
    <App />
  </BrowserRouter>
), document.getElementById('ideas'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router-dom/4.3.1/react-router-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router/4.3.1/react-router.min.js"></script>

<div id="ideas"></div>

actualizaciones:

Ver: https://github.com/ReactTraining/react-router/blob/0c6d51cd6639aff8a84b11d89e27887b3558ed8a/upgrade-guides/v2.0.0.md#link-to-onenter-and-isactive-use-location-descriptors

De la guía de actualización de 1.xa 2.x:

<Link to>, onEnter e isActive usan descriptores de ubicación

<Link to>ahora puede tomar un descriptor de ubicación además de cadenas. La consulta y los accesorios de estado están en desuso.

// v1.0.x

<Link to="/foo" query={{ the: 'query' }}/>

// v2.0.0

<Link to={{ pathname: '/foo', query: { the: 'query' } }}/>

// Sigue siendo válido en 2.x

<Link to="/foo"/>

Del mismo modo, la redirección desde un enlace onEnter ahora también usa un descriptor de ubicación.

// v1.0.x

(nextState, replaceState) => replaceState(null, '/foo')
(nextState, replaceState) => replaceState(null, '/foo', { the: 'query' })

// v2.0.0

(nextState, replace) => replace('/foo')
(nextState, replace) => replace({ pathname: '/foo', query: { the: 'query' } })

Para componentes similares a enlaces personalizados, lo mismo se aplica para router.isActive, anteriormente history.isActive.

// v1.0.x

history.isActive(pathname, query, indexOnly)

// v2.0.0

router.isActive({ pathname, query }, indexOnly)

actualizaciones para v3 a v4:

"documentación de migración heredada" para la posteridad

jmunsch
fuente
3
Parece que params no es compatible con la versión 2.0, asumiendo que los valores de prueba están almacenados en los accesorios, sería algo así como <Link to = { /ideas/${this.props.testvalue}}> {this.props.testvalue} </Link>
Braulio
1
@Braulio gracias. Actualicé mi respuesta e incluí algunos documentos más para las diferencias de <Link> entre v1 y v2
jmunsch
44
@Braulio: la forma correcta es:, <Link to={`/ideas/${this.props.testvalue}`}>{this.props.testvalue}</Link>con
backticks
1
Sí, lo siento, los backticks se perdieron cuando pegué el código para solucionarlo.
Braulio
2
Esto funciona para mí sin usar <Link to={'/ideas/'+this.props.testvalue }>{this.props.testvalue}</Link>
backticks
92

Hay una manera de pasar más de un parámetro. Puede pasar "a" como objeto en lugar de cadena.

// your route setup
<Route path="/category/:catId" component={Category} / >

// your link creation
const newTo = { 
  pathname: "/category/595212758daa6810cbba4104", 
  param1: "Par1" 
};
// link to the "location"
// see (https://reacttraining.com/react-router/web/api/location)
<Link to={newTo}> </Link>

// In your Category Component, you can access the data like this
this.props.match.params.catId // this is 595212758daa6810cbba4104 
this.props.location.param1 // this is Par1
Chetan Sisodiya
fuente
2
exactamente lo que quiero
gramcha
9
Esta respuesta está muy subestimada. No es obvio, pero la documentación menciona este reacttraining.com/react-router/web/api/Link/to-object . Se aconseja pasar los datos como un solo objeto marcado 'estado'
sErVerdevIL
14
Esta es la mejor respuesta a esta pregunta.
Juan Ricardo
¡He estado lidiando con el drama durante demasiado tiempo y esto funcionó totalmente! V4
Mike
1
En la ruta, el atributo no debería ser "/ category / 595212758daa6810cbba4104" en lugar de mapearse al artículo ???
Camilo
38

Tuve el mismo problema para mostrar los detalles de un usuario de mi aplicación.

Puedes hacerlo:

<Link to={'/ideas/'+this.props.testvalue }>Create Idea</Link>

o

<Link to="ideas/hello">Create Idea</Link>

y

<Route name="ideas/:value" handler={CreateIdeaView} />

para obtener esto a través this.props.match.params.valuede su clase CreateIdeaView.

Puedes ver este video que me ayudó mucho: https://www.youtube.com/watch?v=ZBxMljq9GSE

Alessander França
fuente
3
Precisamente lo que dice la documentación. Sin embargo, tengo un caso en el que DESPITE definiendo la ruta como se indicó anteriormente, y configurando el LINK para pasar el valor del parámetro, la clase de componente React no tiene NINGÚN valor this.props.params recogido de la URL. ¿Alguna idea de por qué esto podría suceder? Es como si el enlace de ruta simplemente faltara. El render () en la clase de componente SE ENCIENDE, pero no se pasan datos al componente.
Peter
Pero luego, en su último ejemplo, ¿cómo se extrae la variable 'valor' en el componente CreateIdeaView?
Aspen
20

en cuanto a react-router-dom 4.xx ( https://www.npmjs.com/package/react-router-dom ) puede pasar parámetros al componente para enrutar a través de:

<Route path="/ideas/:value" component ={CreateIdeaView} />

vinculación a través (teniendo en cuenta que el valor testValue se pasa al componente correspondiente (por ejemplo, el componente de la aplicación anterior) que representa el enlace)

<Link to={`/ideas/${ this.props.testValue }`}>Create Idea</Link>

pasando accesorios a su constructor de componentes, el valor param estará disponible vía

props.match.params.value
Kevin K.
fuente
7

Después de instalar react-router-dom

<Link
    to={{
      pathname: "/product-detail",
      productdetailProps: {
       productdetail: "I M passed From Props"
      }
   }}>
    Click To Pass Props
</Link>

y otro extremo donde se redirige la ruta, haga esto

componentDidMount() {
            console.log("product props is", this.props.location.productdetailProps);
          }
Krishna Kumar Jangid
fuente
4

Para resolver la respuesta anterior ( https://stackoverflow.com/a/44860918/2011818 ), también puede enviar los objetos en línea "A" dentro del objeto Enlace.

<Route path="/foo/:fooId" component={foo} / >

<Link to={{pathname:/foo/newb, sampleParam: "Hello", sampleParam2: "World!" }}> CLICK HERE </Link>

this.props.match.params.fooId //newb
this.props.location.sampleParam //"Hello"
this.props.location.sampleParam2 //"World!"
FBaez51
fuente
3

Mecanografiado

Para el enfoque mencionado de esta manera en muchas respuestas,

<Link
    to={{
        pathname: "/my-path",
        myProps: {
            hello: "Hello World"
        }
    }}>
    Press Me
</Link>

Estaba recibiendo un error

El literal de objeto solo puede especificar propiedades conocidas, y 'myProps' no existe en el tipo 'LocationDescriptorObject | ((location: Location) => LocationDescriptor) '

Luego revisé la documentación oficial que me proporcionaronstate para el mismo propósito.

Entonces funcionó así,

<Link
    to={{
        pathname: "/my-path",
        state: {
            hello: "Hello World"
        }
    }}>
    Press Me
</Link>

Y en su próximo componente puede obtener este valor de la siguiente manera,

componentDidMount() {
    console.log("received "+this.props.location.state.hello);
}
gprathour
fuente
Gracias @gprathour
Akshay Vijay Jain
0

Ruta:

<Route state={this.state} exact path="/customers/:id" render={(props) => <PageCustomer {...props} state={this.state} />} />

Y luego se puede acceder params en su componente PageCustomer como esto: this.props.match.params.id.

Por ejemplo, una llamada a la API en el componente PageCustomer:

axios({
   method: 'get',
   url: '/api/customers/' + this.props.match.params.id,
   data: {},
   headers: {'X-Requested-With': 'XMLHttpRequest'}
 })
Abu Shumon
fuente