react-router-przekazuje właściwości do komponentu obsługi

Mam następującą strukturę dla mojej reakcji.aplikacja js korzystająca z routera Reactowego :

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

Chcę przekazać niektóre właściwości do komponentu Comments.

(normalnie zrobiłbym to jak <Comments myprop="value" />)

Jaki jest najprostszy i właściwy sposób na Router Reactowy?

Author: icc97, 2015-01-09

20 answers


UPDATE od nowej wersji możliwe jest przekazywanie właściwości bezpośrednio przez komponent Route, bez użycia wrappera

Na przykład, używając render prop. Link do routera reactowego: https://reacttraining.com/react-router/web/api/Route/render-func

Przykład kodu w codesandbox: https://codesandbox.io/s/z3ovqpmp44

Komponent

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

I użycie

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

STARA WERSJA

My preferred way jest wrap komponentu Comments i przekazuje wrapper jako obsługę trasy.

Oto przykład z zastosowanymi zmianami:

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);
});
 104
Author: ColCh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-20 19:44:57

Jeśli wolisz nie pisać wrapperów, to chyba możesz to zrobić:

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}/>
);
 251
Author: Thomas E,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-01 14:00:52

Kopiowanie z komentarzy przez ciantic w zaakceptowanej odpowiedzi:

<Route path="comments" component={() => (<Comments myProp="value" />)}/>
Jest to moim zdaniem najbardziej wdzięczne rozwiązanie. To działa. Pomógł mi.
 110
Author: Rajesh Naroth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:27

To jest rozwiązanie od Rajesh, bez niewygodnego komentowanego przez yuji i zaktualizowanego dla Reactowego routera 4.

Kod będzie wyglądał następująco:

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

Zauważ, że używam render zamiast component. Powodem jest unikanie niepożądanego remountu . Przekazuję również props do tej metody i używam tych samych właściwości w komponencie Comments z operatorem rozprzestrzeniania obiektów (propozycja ES7).

 47
Author: Daniel Reina,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-28 18:23:28

To tylko kontynuacja odpowiedzi Colcha. Jest to dość łatwe do abstrakcji owijanie komponentu:

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

Nie testowałem jeszcze tego rozwiązania, więc każda opinia jest ważna.

Ważne jest, aby pamiętać, że dzięki tej metodzie wszystkie rekwizyty wysyłane przez Router (takie jak params) zostają nadpisane / usunięte.

 43
Author: sigmus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-29 18:01:28

Możesz przekazać rekwizyty, przekazując je do <RouteHandler> (w wersji 0.13.x) lub samego komponentu trasy w v1. 0;

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

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

(z podręcznika aktualizacji na https://github.com/rackt/react-router/releases/tag/v1.0.0 )

Wszyscy opiekunowie dzieci otrzymają ten sam zestaw rekwizytów - może to być przydatne lub nie w zależności od okoliczności.

 30
Author: cachvico,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-23 20:55:59

Za pomocą ES6 możesz po prostu tworzyć wrappery komponentów inline:

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

Jeśli trzeba przekazać dzieci:

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

 23
Author: Nick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-14 23:18:37

React-router v4 alpha

Teraz jest nowy sposób, aby to zrobić, choć bardzo podobny do poprzedniej metody.

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. to działa tylko w wersji alfa i zostały usunięte po wydaniu alpha v4. W V4 Najnowszy, jest po raz kolejny, ze ścieżką i dokładnymi rekwizytami.

React-lego przykładowa aplikacja zawiera kod, który robi dokładnie to w trasach.js na swojej gałęzi react-router-4

 22
Author: peter.mouland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-08 12:15:01

Oto najczystsze rozwiązanie ,jakie wymyśliłem (React Router v4):

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

MyComponent nadal ma props.match i props.location i ma props.foo === "lol".

 18
Author: cgenco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-20 00:04:23

Możesz również użyć RouteHandler mixin, aby uniknąć komponentu wrappera i łatwiej przekazać stan rodzica jako właściwości:

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);
});
 11
Author: jul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-27 21:56:28

Możesz przekazać rekwizyty za pomocą <RouterHandler/> w następujący sposób:

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>
    );
  }
});
Minusem tego jest to, że przekazujesz rekwizyty bezkrytycznie. Więc Comments może skończyć się otrzymaniem rekwizytów, które są naprawdę przeznaczone dla innego komponentu w zależności od konfiguracji tras. Nie jest to wielka sprawa, ponieważ props jest niezmienna, ale może to być problematyczne, jeśli dwa różne komponenty oczekują właściwości o nazwie foo, ale o różnych wartościach.
 11
Author: Meistro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-27 19:10:04

Owiń go składnikiem funkcji bezstanowej:

<Router>
  <Route 
    path='/' 
    component={({children}) => 
      <MyComponent myProp={'myVal'}>{children}</MyComponent/>
    }/>
</Router>
 11
Author: mg74,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-25 03:54:58

W 1.0 i 2.0 możesz użyć createElement prop of Router aby określić, jak dokładnie utworzyć element docelowy. Źródło dokumentacji

function createWithDefaultProps(Component, props) {
    return <Component {...props} myprop="value" />;
}

// and then    
<Router createElement={createWithDefaultProps}>
    ...
</Router>
 9
Author: Andrew Khmylov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-11 10:42:42

Możesz również połączyć funkcje ES6 i stateless , aby uzyskać znacznie czystszy wynik:

import Dashboard from './Dashboard';
import Comments from './Comments';

let dashboardWrapper = () => <Dashboard {...props} />,
    commentsWrapper = () => <Comments {...props} />,
    index = () => <div>
        <header>Some header</header>
        <RouteHandler />
        {this.props.children}
    </div>;

routes = {
    component: index,
    path: '/',
    childRoutes: [
      {
        path: 'comments',
        component: dashboardWrapper
      }, {
        path: 'dashboard',
        component: commentsWrapper
      }
    ]
}
 5
Author: Zhiwei Huang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-27 19:19:38

Dla reactowego routera 2.x.

const WrappedComponent = (Container, propsToPass, { children }) => <Container {...propsToPass}>{children}</Container>;
I na Twoich trasach...
<Route path="/" component={WrappedComponent.bind(null, LayoutContainer, { someProp })}>
</Route>

Upewnij się, że trzeci param jest obiektem typu: { checked: false }.

 4
Author: holyxiaoxin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-14 10:04:58

React Router v 4 solution

Natknąłem się dziś na to pytanie i oto wzór, którego używam. Mam nadzieję, że jest to przydatne dla każdego, kto szuka bardziej aktualnego rozwiązania.

Nie jestem pewien, czy to jest najlepsze rozwiązanie, ale to jest mój obecny wzór na to. Zazwyczaj mam Katalog Core, w którym przechowuję moje często używane komponenty z ich odpowiednimi konfiguracjami( Ładowarki, Modale itp.), i dołączam plik taki jak to:
import React from 'react'
import { Route } from 'react-router-dom'

const getLocationAwareComponent = (component) => (props) => (
  <Route render={(routeProps) => React.createElement(component, 
{...routeProps, ...props})}/>
)

export default getLocationAwareComponent

Następnie, w danym pliku, zrobię co następuje:

import React from 'react'
import someComponent from 'components/SomeComponent'
import { getLocationAwareComponent } from 'components/Core/getLocationAwareComponent'
const SomeComponent = getLocationAwareComponent(someComponent)

// in render method:
<SomeComponent someProp={value} />

Zauważysz, że importuję domyślny eksport mojego komponentu jako humble camel-case, co pozwala mi nazwać nowy, zorientowany na lokalizację komponent w CamelCase, więc mogę go używać normalnie. Oprócz dodatkowej linii importu i linii przypisania komponent zachowuje się zgodnie z oczekiwaniami i odbiera wszystkie swoje właściwości normalnie, z dodaniem wszystkich właściwości trasy. W ten sposób mogę szczęśliwie przekierować z komponentu metody cyklu życia z tym.rekwizyty.historia.push (), Sprawdź lokalizację itp.

Mam nadzieję, że to pomoże!
 4
Author: Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-22 20:21:19

Problem z routerem Reactowym polega na tym, że renderuje on komponenty i w ten sposób uniemożliwia wklejanie rekwizytów. Z kolei Router nawigacyjny pozwala na renderowanie własnych komponentów. Oznacza to, że nie musisz przeskakiwać przez żadne obręcze, aby przejść w rekwizytach jako następujący kod i towarzyszący jsfiddle show.

var Comments = ({myProp}) => <div>{myProp}</div>;

var stateNavigator = new Navigation.StateNavigator([
  {key:'comments', route:''}
]);

stateNavigator.states.comments.navigated = function(data) {
  ReactDOM.render(
    <Comments myProp="value" />,
    document.getElementById('content')
  );
}

stateNavigator.start();
 1
Author: graham mendick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-20 10:42:46

Użyj komponentu z routerem lub bez niego na podstawie odpowiedzi Rajesha Narotha.

class Index extends React.Component {

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

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

Lub twój mógłby to zrobić w ten sposób:

export const Index = ({foo, route}) => {
  const content = (foo) ? foo : (route) ? route.foo : 'No content found!';
  return <h1>{content}</h1>
};
 1
Author: Michael Hobbs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-02 13:23:39

Dla react-routera 2.5.2 rozwiązanie jest takie proste:

    //someConponent
...
render:function(){
  return (
    <h1>This is the parent component who pass the prop to this.props.children</h1>
    {this.props.children && React.cloneElement(this.props.children,{myProp:'value'})}
  )
}
...
 0
Author: min may,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-11 03:41:40

Użycie komponentu trasy jest to możliwe w Reactowym routerze v3.

var Dashboard = require('./Dashboard');
var Comments = require('./Comments');
var routes = (
  <Route path="/" handler={Index}>
    <MyRoute myprop="value" path="comments" handler={Comments}/>
    <DefaultRoute handler={Dashboard}/>
  </Route>
);

Jeśli chodzi o kod komponentu <MyRoute>, powinno być to coś w stylu:

import React from 'react';
import { Route } from 'react-router';
import { createRoutesFromReactChildren } from 'react-router/lib//RouteUtils';

const MyRoute = () => <div>&lt;MyRoute&gt; elements are for configuration only and should not be rendered</div>;

MyRoute.createRouteFromReactElement = (element, parentRoute) => {
    const { path, myprop } = element.props;
    // dynamically add crud route
    const myRoute = createRoutesFromReactChildren(
        <Route path={path} />,
        parentRoute
    )[0];
    // higher-order component to pass myprop as resource to components
    myRoute.component = ({ children }) => (
        <div>
            {React.Children.map(children, child => React.cloneElement(child, { myprop }))}
        </div>
    );
    return myRoute;
};

export default MyRoute;

Aby dowiedzieć się więcej o niestandardowym podejściu do komponentu trasy, zajrzyj do mojego posta na blogu na ten temat: http://marmelab.com/blog/2016/09/20/custom-react-router-component.html

 0
Author: François Zaninotto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-20 15:53:25