Website-Suche

javascript - react-router - Props an Handler-Komponente übergeben


Ich habe die folgende Struktur für meine React.js-Anwendung unter Verwendung von React Router:

var Dashboard = require('./Dashboard');
var Comments = require('./Comments');

var Index = React.createClass({
  render: function () {
    return (
        <div>
            <header>Some header</header>
            <RouteHandler />
        </div>
    );
  }
});

var routes = (
  <Route path="/" handler={Index}>
    <Route path="comments" handler={Comments}/>
    <DefaultRoute handler={Dashboard}/>
  </Route>
);

ReactRouter.run(routes, function (Handler) {
  React.render(<Handler/>, document.body);
});

Ich möchte einige Eigenschaften in die Comments-Komponente übergeben.

(normalerweise würde ich das so machen <Comments myprop="value" />)

Was ist der einfachste und richtige Weg, dies mit React Router zu tun?

Antwort #1

Wenn Sie lieber keine Wrapper schreiben möchten, könnten Sie das wohl so machen:

class Index extends React.Component { 

  constructor(props) {
    super(props);
  }
  render() {
    return (
      <h1>
        Index - {this.props.route.foo}
      </h1>
    );
  }
}

var routes = (
  <Route path="/" foo="bar" component={Index}/>
);

Antwort #2

AKTUALISIEREN

Seit der neuen Version ist es möglich, Props direkt über die Route-Komponente zu übergeben, ohne einen Wrapper zu verwenden. Zum Beispiel durch die Verwendung der render-Prop.

Komponente:

class Greeting extends React.Component {
  render() {
    const {text, match: {params}} = this.props;

    const {name} = params;

    return (
      <React.Fragment>
        <h1>Greeting page</h1>
        <p>
          {text} {name}
        </p>
      </React.Fragment>
    );
  }
}

Verwendung:

<Route path="/greeting/:name" render={(props) => <Greeting text="Hello, " {...props} />} />

Codesandbox Beispiel

ALTE VERSION

Meine bevorzugte Methode ist, die Comments-Komponente einzuwickeln und den Wrapper als Routen-Handler zu übergeben.

Dies ist Ihr Beispiel mit angewendeten Änderungen:

var Dashboard = require('./Dashboard');
var Comments = require('./Comments');

var CommentsWrapper = React.createClass({
  render: function () {
    return (
      <Comments myprop="myvalue"/>
    );
  }
});

var Index = React.createClass({
  render: function () {
    return (
      <div>
        <header>Some header</header>
        <RouteHandler/>
      </div>
    );
  }
});

var routes = (
  <Route path="/" handler={Index}>
    <Route path="comments" handler={CommentsWrapper}/>
    <DefaultRoute handler={Dashboard}/>
  </Route>
);

ReactRouter.run(routes, function (Handler) {
  React.render(<Handler/>, document.body);
});

Antwort #3

Kopieren aus den Kommentaren von ciantic in der akzeptierten Antwort:

<Route path="comments" component={() => (<Comments myProp="value" />)}/>

Dies ist meiner Meinung nach die eleganteste Lösung. Sie funktioniert. Hat mir geholfen.

Antwort #4

Dies ist die Lösung von Rajesh, ohne die von Yuji unpraktischerweise kommentierten Teile und aktualisiert für React Router 4.

Der Code wäre so:

<Route path="comments" render={(props) => <Comments myProp="value" {...props}/>}/>

Beachten Sie, dass ich render anstelle von component verwende. Der Grund ist, unerwünschtes erneutes Mounten zu vermeiden. Ich übergebe auch die props an diese Methode, und ich verwende dieselben Props in der Comments-Komponente mit dem Objekt-Spread-Operator (ES7-Vorschlag).

Antwort #5

Nur eine Nachverfolgung zu ColChs Antwort. Es ist ziemlich einfach, das Einhüllen einer Komponente zu abstrahieren:

var React = require('react');

var wrapComponent = function(Component, props) {
  return React.createClass({
    render: function() {
      return React.createElement(Component, props);
    }
  });
};

<Route path="comments" handler={wrapComponent(Comments, {myprop: value})}/>

Ich habe diese Lösung noch nicht getestet, daher ist jedes Feedback wichtig.

Es ist wichtig zu beachten, dass bei dieser Methode alle über den Router gesendeten Props (wie Parameter) überschrieben oder entfernt werden.

Antwort #6

Sie können Props weitergeben, indem Sie sie an <RouteHandler> (in v0.13.x) oder an die Route-Komponente selbst in v1.0 übergeben;

// v0.13.x
<RouteHandler/>
<RouteHandler someExtraProp={something}/>

// v1.0
{this.props.children}
{React.cloneElement(this.props.children, {someExtraProp: something })}

(aus dem Upgrade-Leitfaden auf https://github.com/rackt/react-router/releases/tag/v1.0.0)

Alle Kind-Handler erhalten denselben Satz von Props - dies kann je nach Umstand nützlich sein oder nicht.

Antwort #7

Mit ES6 können Sie Komponentenhüllen einfach inline erstellen:

<Route path="/" component={() => <App myProp={someValue}/>} >

Wenn Sie Kinder mitnehmen müssen:

<Route path="/" component={(props) => <App myProp={someValue}>{props.children}</App>} >

Antwort #8

React-router v4 Alpha

Jetzt gibt es einen neuen Weg, dies zu tun, obwohl er dem vorherigen Verfahren sehr ähnlich ist.

import { Match, Link, Miss } from 'react-router';
import Homepage from './containers/Homepage';

const route = {
    exactly: true,
    pattern: '/',
    title: `${siteTitle} - homepage`,
    component: Homepage
  }

<Match { ...route } render={(props) => <route.component {...props} />} />

P.S. Dies funktioniert nur in der Alpha-Version, und wurden nach der v4-Alpha-Veröffentlichung entfernt. In v4 neuestem ist erneut , mit dem Pfad und genauen Eigenschaften.

react-lego eine Beispiel-App enthält Code, der genau dies in routes.js auf ihrem react-router-4-Branch macht

Antwort #9

Hier ist die sauberste Lösung, die mir eingefallen ist (React Router v4):

<Route
  path="/"
  component={props => <MyComponent {...props} foo="lol" />}
/>

MyComponent hat immer noch props.match und props.location und hat props.foo === "lol".

Antwort #10

Wickeln Sie es mit einer zustandslosen Funktionskomponente ein:

<Router>
  <Route 
    path='/' 
    component={({children}) => 
      <MyComponent myProp={'myVal'}>{children}</MyComponent/>
    }/>
</Router>

Antwort #11

Sie könnten auch das RouteHandler-Mixin verwenden, um die Wrapper-Komponente zu vermeiden und den Zustand des übergeordneten Elements einfacher als Props weiterzugeben:

var Dashboard = require('./Dashboard');
var Comments = require('./Comments');
var RouteHandler = require('react-router/modules/mixins/RouteHandler');

var Index = React.createClass({
      mixins: [RouteHandler],
      render: function () {
        var handler = this.getRouteHandler({ myProp: 'value'});
        return (
            <div>
                <header>Some header</header>
                {handler}
           </div>
        );
  }
});

var routes = (
  <Route path="/" handler={Index}>
    <Route path="comments" handler={Comments}/>
    <DefaultRoute handler={Dashboard}/>
  </Route>
);

ReactRouter.run(routes, function (Handler) {
  React.render(<Handler/>, document.body);
});

Antwort #12

Sie können Props über den <RouterHandler/> wie folgt übergeben:

var Dashboard = require('./Dashboard');
var Comments = require('./Comments');

var Index = React.createClass({
  render: function () {
    var props = this.props; // or possibly this.state
    return (
        <div>
            <header>Some header</header>
            <RouteHandler {...props} />
        </div>
    );
  }
});

Der Nachteil davon ist, dass Sie Props wahllos weitergeben. Dadurch kann es passieren, dass Comments Props erhält, die eigentlich für eine andere Komponente vorgesehen sind, abhängig von Ihrer Routen-Konfiguration. Es ist kein großes Problem, da props unveränderlich ist, aber es kann problematisch werden, wenn zwei verschiedene Komponenten eine Prop namens foo erwarten, aber mit unterschiedlichen Werten.

Verwandte Artikel