Réagir routeur et ce.accessoires de jeu.enfants-comment passer l'État à cela.accessoires de jeu.enfant

J'utilise React-router pour la première fois et je ne sais pas encore comment y penser. Voici comment je charge mes composants dans les routes imbriquées.

Point d'entrée .js

ReactDOM.render(
    <Router history={hashHistory} >
        <Route path="/" component={App}>
            <Route path="models" component={Content}>
        </Route>
    </Router>, 
    document.getElementById('app')
);

App.js

  render: function() {
    return (
      <div>
        <Header />
        {this.props.children}
      </div>
    );
  }

Donc, l'enfant de mon application est le composant de contenu que j'ai envoyé. J'utilise Flux et mon application.js a l'état et écoute les changements, mais je ne sais pas comment transmettre cet état à ceci.accessoires de jeu.enfant. Avant d'utiliser react-router mon application.js définit tous les enfants explicitement, donc passer l'État était naturel mais je ne vois pas comment le faire maintenant.

25
demandé sur Patrick 2016-03-07 06:24:47

3 réponses

Cette question se résume à, Comment passez-vous des accessoires aux enfants?

Juin 2018 réponse

La technologie D'Aujourd'hui:


En supposant un composant avec État:

import React from 'react'
import { BrowserRouter, Route } from 'react-router-dom'

// some component you made
import Title from './Title'

class App extends React.Component {
  // this.state
  state = { title: 'foo' }

  // this.render
  render() {
    return (
      <BrowserRouter>

        // when the url is `/test` run this Route's render function:
        <Route path="/:foobar" render={

          // argument is props passed from `<Route /`>
          routeProps => 

            // render Title component
            <Title 
              // pass this.state values
              title={this.state.title}

              // pass routeProps values (url stuff)
              page={routeProps.match.params.foobar} // "test"
            />

        } />

      </BrowserRouter>
    )
  }
}

Cela fonctionne parce que cette.accessoires de jeu.les enfants est une fonction:

// "smart" component aka "container"
class App extends React.Component {
  state = { foo: 'bar' }
  render() {
    return this.props.children(this.state.foo)
  }
}

// "dumb" component aka "presentational"
const Title = () => (
  <App>
    {title => <h1>{title}</h1>}
  </App>
)

Exemple sur codesandbox

Ma précédente réponse oldschool que je ne recommanderais plus:

En utilisant quelques méthodes React helper, vous pouvez ajouter de l'état, des accessoires et tout le reste à this.props.children

render: function() {
  var children = React.Children.map(this.props.children, function (child) {
    return React.cloneElement(child, {
      foo: this.state.foo
    })
  })

  return <div>{children}</div>
}

Ensuite, votre composant enfant peut y accéder via props, this.props.foo.

30
répondu azium 2018-06-16 03:01:16

Vous pouvez utiliser la méthode React "cloneElement" pour y parvenir. Lorsque vous clonez l'élément, vous pouvez passer des accessoires à ce moment-là. Utilisez le clone au lieu de l'original dans votre FN de rendu. par exemple:

    render: function() {
    var childrenWithProps = React.cloneElement(this.props.children, {someProp: this.state.someProp});
    return (
      <div>
        <Header />
        {childrenWithProps}
      </div>
    );
  }
10
répondu Jess Scheuring 2016-03-08 04:51:45

Il y a aussi la possibilité d'utiliser Context. React-Router s'en appuie pour donner accès à L'objet routeur dans les composants de la route.

D'autre réponse j'ai donné sur une question similaire:

J'ai rapidement mis en place un exemple utilisant des contextes sur codepen . MainLayout définit certaines propriétés qui pourraient être utilisées par les enfants en utilisant le contexte: users et widgets. Ces propriétés sont utilisées par les composants UserList et WidgetList. Remarquez qu'ils doivent définir quoi ils doivent accéder à partir du contexte dans l'objet contextTypes.

var { Router, Route, IndexRoute, Link } = ReactRouter

var MainLayout = React.createClass({
  childContextTypes: {
    users: React.PropTypes.array,
    widgets: React.PropTypes.array,
  },
  getChildContext: function() {
    return {
      users: ["Dan", "Ryan", "Michael"], 
      widgets: ["Widget 1", "Widget 2", "Widget 3"]
    };
  },
  render: function() {
    return (
      <div className="app">
        <header className="primary-header"></header>
        <aside className="primary-aside">
          <ul>
            <li><Link to="/">Home</Link></li>
            <li><Link to="/users">Users</Link></li>
            <li><Link to="/widgets">Widgets</Link></li>
          </ul>
        </aside>
        <main>
          {this.props.children}
        </main>
      </div>
      )
  }
})

var Home = React.createClass({
  render: function() {
    return (<h1>Home Page</h1>)
  }
})

var SearchLayout = React.createClass({
  render: function() {
    return (
      <div className="search">
        <header className="search-header"></header>
        <div className="results">
          {this.props.children}
        </div>
        <div className="search-footer pagination"></div>
      </div>
      )
  }
})

var UserList = React.createClass({
  contextTypes: {
    users: React.PropTypes.array
  },
  render: function() {
    return (
      <ul className="user-list">
        {this.context.users.map(function(user, index) {
          return <li key={index}>{user}</li>;  
        })}
      </ul>
      )
  }
})

var WidgetList = React.createClass({
  contextTypes: {
    widgets: React.PropTypes.array
  },
  render: function() {
    return (
      <ul className="widget-list">
        {this.context.widgets.map(function(widget, index) {
          return <li key={index}>{widget}</li>;  
        })}
      </ul>
      )
  }
})

var Routes = React.createClass({
  render: function() {
    return <Router>
        <Route path="/" component={MainLayout}>
          <IndexRoute component={Home} />
          <Route component={SearchLayout}>
            <Route path="users" component={UserList} />
            <Route path="widgets" component={WidgetList} />
          </Route> 
        </Route>
      </Router>;
  }
})

ReactDOM.render(<Routes/>, document.getElementById('root'))
2
répondu Alex Chirițescu 2017-05-23 12:02:45