2016-03-07 9 views
24

Używam React-routera po raz pierwszy i nie wiem jak jeszcze w nim myśleć. Oto jak ładuję moje komponenty w zagnieżdżonych trasach.React router and this.props.children - jak przekazać stan this.props.children

punkt wejścia 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> 
    ); 
    } 

Więc dziecko mojej aplikacji jest składnikiem treści wysłałem. Używam Flux i My App.js ma stan i nasłuchuje zmian, ale nie wiem, jak przekazać ten stan do this.props.children. Przed użyciem routera reagującego mój app.js definiuje jawnie wszystkie dzieci, więc przekazanie stanu było naturalne, ale nie widzę teraz, jak to zrobić.

+1

Możliwe duplikat [Jak przechodzą podpory {this.props.children}] (http://stackoverflow.com/questions/32370994/how-to-pass-props-to-this-props- dzieci) –

Odpowiedz

27

Korzystanie parę React metody pomocnika można dodać stan, rekwizyty i cokolwiek innego 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> 
} 

Następnie komponent dziecko może uzyskać dostęp do tego za pomocą rekwizytów, this.props.foo.

+0

Tak, czytałem o dziecku pomocnika i widziałem to. Dlaczego warto korzystać z mapy zamiast z ForEach? – Patrick

+1

Ogólnie zaleca się, aby nie mutować danych, jeśli możesz pomóc. Jest to dobra praktyka w programowaniu, nie tylko w przypadku React. Wykonuj mutacje tylko wtedy, gdy nie ma innego możliwego rozwiązania - jest to rzadki przypadek. – azium

+0

Zgadzam się na mutacje, ale wydaje mi się, że nie widzę połączenia - czy ForEach koniecznie mutuje stan? – Patrick

10

Do wykonania tej czynności można użyć React method "cloneElement". Kiedy sklonujesz element, możesz w tym czasie przekazać rekwizyty. Użyj klonu zamiast oryginału w twoim renderowaniu fn. np .:

render: function() { 
    var childrenWithProps = React.cloneElement(this.props.children, {someProp: this.state.someProp}); 
    return (
     <div> 
     <Header /> 
     {childrenWithProps} 
     </div> 
    ); 
    } 
+0

Brakujące nawiasy klamrowe wokół 'childrenWithProps' – azium

+0

Czy Twój przykład sklonuje wszystkie dzieci lub tylko jedno w przypadku, gdy this.props.children ma tylko jeden element? Widziałem inny przykład na stackoverflow, ale wydawało mi się to błędne, że musiałbym ręcznie go przerabiać, aby wykonać podstawowe rekwizyty. – Patrick

+1

@Patrick Jeśli spojrzysz na moją odpowiedź, najpierw zobaczysz "Children.map". Jest to potrzebne, zazwyczaj dlatego, że 'children' może być obiektem lub tablicą, a w drugim przypadku klonować każdy element. – azium

2

Istnieje również możliwość użycia Context. React-Router polega na umożliwieniu dostępu do obiektu Router w komponentach trasy.

Z innej answer dałem na podobnym pytaniem:

Szybko zebrała przykład przy użyciu kontekstów na codepen. MainLayout definiuje niektóre właściwości, które mogą być używane przez dzieci w kontekście: users i widgets. Te właściwości są używane przez komponenty UserList i WidgetList. Zauważ, że muszą zdefiniować, czego potrzebują, aby uzyskać dostęp z kontekstu w obiekcie 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')) 
Powiązane problemy