web-dev-qa-db-fra.com

React-router: Comment appeler manuellement Link?

Je suis nouveau sur ReactJS et React-Router. J'ai un composant qui reçoit, via les accessoires, un objet <Link/> de react-router. Chaque fois que l'utilisateur clique sur un bouton "Suivant" dans ce composant, je souhaite appeler l'objet <Link/> manuellement.

En ce moment, j'utilise refs pour accéder à instance de sauvegarde et je clique manuellement sur la balise 'a' générée par <Link/>

Question: Existe-t-il un moyen d'invoquer manuellement le lien (par exemple this.props.next.go)?

C'est le code actuel que j'ai:

//in MasterPage.js
var sampleLink = <Link to="/sample">Go To Sample</Link>
<Document next={sampleLink} />

//in Document.js
...
var Document = React.createClass({
   _onClickNext: function() {
      var next = this.refs.next.getDOMNode();
      next.querySelectorAll('a').item(0).click(); //this sounds like hack to me
   },
   render: function() {
      return (
         ...
         <div ref="next">{this.props.next} <img src="rightArrow.png" onClick={this._onClickNext}/></div>
         ...
      );
   }
});
...

C'est le code que j'aimerais avoir:

//in MasterPage.js
var sampleLink = <Link to="/sample">Go To Sample</Link>
<Document next={sampleLink} />

//in Document.js
...
var Document = React.createClass({
   render: function() {
      return (
         ...
         <div onClick={this.props.next.go}>{this.props.next.label} <img src="rightArrow.png" /> </div>
         ...
      );
   }
});
...
79
Alan Souza

React Router v4 - Composant de redirection (mise à jour le 15/04/2017)

La méthode recommandée par la v4 consiste à autoriser votre méthode de rendu à intercepter une redirection. Utilisez state ou props pour déterminer si le composant de redirection doit être affiché (ce qui déclenche alors une redirection).

import { Redirect } from 'react-router';

// ... your class implementation

handleOnClick = () => {
  // some action...
  // then redirect
  this.setState({redirect: true});
}

render() {
  if (this.state.redirect) {
    return <Redirect Push to="/sample" />;
  }

  return <button onClick={this.handleOnClick} type="button">Button</button>;
}

Référence: https://reacttraining.com/react-router/web/api/Redirect

React Router v4 - Contexte du routeur de référence

Vous pouvez également tirer parti du contexte de Router exposé au composant React.

static contextTypes = {
  router: PropTypes.shape({
    history: PropTypes.shape({
      Push: PropTypes.func.isRequired,
      replace: PropTypes.func.isRequired
    }).isRequired,
    staticContext: PropTypes.object
  }).isRequired
};

handleOnClick = () => {
  this.context.router.Push('/sample');
}

Voici comment <Redirect /> fonctionne sous le capot.

Référence: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Redirect.js#L46,L60

React Router v4 - Objet historique muté de manière externe

Si vous avez encore besoin de faire quelque chose de similaire à l'implémentation de la version 2, vous pouvez créer une copie de BrowserRouter, puis exposer history en tant que constante exportable. Vous trouverez ci-dessous un exemple élémentaire, mais vous pouvez le composer pour l’injecter des accessoires personnalisables si nécessaire. Il existe des mises en garde concernant les cycles de vie, mais il convient de toujours rendre le routeur, tout comme dans la v2. Cela peut être utile pour les redirections après une demande d'API à partir d'une fonction d'action.

// browser router file...
import createHistory from 'history/createBrowserHistory';
import { Router } from 'react-router';

export const history = createHistory();

export default class BrowserRouter extends Component {
  render() {
    return <Router history={history} children={this.props.children} />
  }
}

// your main file...
import BrowserRouter from './relative/path/to/BrowserRouter';
import { render } from 'react-dom';

render(
  <BrowserRouter>
    <App/>
  </BrowserRouter>
);

// some file... where you don't have React instance references
import { history } from './relative/path/to/BrowserRouter';

history.Push('/sample');

Dernière BrowserRouter à prolonger: https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/BrowserRouter.js

React Router v2

Poussez un nouvel état dans l'instance browserHistory:

import {browserHistory} from 'react-router';
// ...
browserHistory.Push('/sample');

Référence: https://github.com/reactjs/react-router/blob/master/docs/guides/NavigatingOutsideOfComponents.md

147
Matt Lo

React Router 4 comprend un withRouterHOC qui vous donne accès à l’objet history via this.props:

import React, {Component} from 'react'
import {withRouter} from 'react-router-dom'

class Foo extends Component {
  constructor(props) {
    super(props)

    this.goHome = this.goHome.bind(this)
  }

  goHome() {
    this.props.history.Push('/')
  }

  render() {
    <div className="foo">
      <button onClick={this.goHome} />
    </div>
  }
}

export default withRouter(Foo)
62
aw04

https://github.com/rackt/react-router/blob/bf89168acb30b6dc9b0244360bcbac5081cf6b38/examples/transitions/app.js#L50

ou vous pouvez même essayer d’exécuter onClick (solution plus violente):

window.location.assign("/sample");
3
grechut

Ok, je pense que j'ai été capable de trouver une solution adéquate pour cela.

Maintenant, au lieu d’envoyer <Link/> en tant que prop à Document, j’envoie <NextLink/> qui est un wrapper personnalisé pour le lien react-router. En faisant cela, je peux avoir la flèche vers la droite dans la structure de lien tout en évitant d’avoir un code de routage dans l’objet Document.

Le code mis à jour se présente comme suit:

//in NextLink.js
var React = require('react');
var Right = require('./Right');

var NextLink = React.createClass({
    propTypes: {
        link: React.PropTypes.node.isRequired
    },

    contextTypes: {
        transitionTo: React.PropTypes.func.isRequired
    },

    _onClickRight: function() {
        this.context.transitionTo(this.props.link.props.to);
    },

    render: function() {
        return (
            <div>
                {this.props.link}
                <Right onClick={this._onClickRight} />
            </div>  
        );
    }
});

module.exports = NextLink;

...
//in MasterPage.js
var sampleLink = <Link to="/sample">Go To Sample</Link>
var nextLink = <NextLink link={sampleLink} />
<Document next={nextLink} />

//in Document.js
...
var Document = React.createClass({
   render: function() {
      return (
         ...
         <div>{this.props.next}</div>
         ...
      );
   }
});
...

P.S : Si vous utilisez la dernière version de react-router, vous devrez peut-être utiliser this.context.router.transitionTo au lieu de this.context.transitionTo. Ce code fonctionnera correctement pour react-router version 0.12.X.

2
Alan Souza

encore une fois c'est JS :) cela fonctionne toujours ....

var linkToClick = document.getElementById('something');
linkToClick.click();

<Link id="something" to={/somewhaere}> the link </Link>
0
Taggart Jensen