2016-03-07 14 views
24

私はリアクタを初めて使用していますが、私はそれについてどう考えているのか分かりません。ここでは、コンポーネントをネストされたルートでロードしています。リアクタとthis.props.children - どのようにthis.props.childrenに状態を渡すか

エントリポイントが

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

だから、私のアプリの子供は私がフラックスを使用して、私のしています。中に送信されたコンテンツ構成要素であるが.jsファイルApp.jsには状態があり、変更をリッスンしますが、この状態をthis.props.childrenに渡す方法はわかりません。反応ルータを使用する前に、私のApp.jsはすべての子を明示的に定義しているので、状態を渡すことは自然でしたが、今はそれをどうやって行うのか分かりません。あなたはその後、あなたの子コンポーネントは、小道具、this.props.fooを経由して、これをアクセスすることができます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> 
} 

の状態、小道具や他のものは何でもを追加することができますリアクトヘルパーメソッドのカップルを使用して

+1

の可能性のある重複[{this.props.children}に小道具を渡す方法](http://stackoverflow.com/questions/32370994/how-to-pass-props-to-this-props-子供) –

答えて

27

+0

さて、私は子供のヘルパーについて読んでこれを見ていました。なぜ、ForEachではなくMapを使うのですか? – Patrick

+1

一般的に、データを助けることができれば、データを変更しないことをお勧めします。これは、Reactだけでなく、一般的にプログラミングの良い練習です。可能な解決策が他にない場合にのみ変異を作ります---これはまれなケースです。 – azium

+0

私は突然変異について同意するが、私は接続が見えないと思う - ForEachは必然的に状態を変異させるのだろうか? – Patrick

10

これを実現するにはReact method "cloneElement"を使用できます。要素を複製すると、その時点で小道具を渡すことができます。レンダリングfnでオリジナルの代わりにクローンを使用します。例:

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

'childrenWithProps'の周りに中括弧がありません – azium

+0

this.props.childrenが1つの要素しか持たない場合、すべての子をクローンしますか?私はstackoverflow上の他の例を見ましたが、私は手動で基本的な小道具を渡すためにそれらを介して反復する必要があることは間違っているように見えました。 – Patrick

+1

@パトリック私の答えを見ると、まず「Children.map」に気付くでしょう。これは、通常は 'children'がオブジェクトまたは配列である可能性があり、後者の場合、各要素を複製するために必要です。 – azium

2

Contextのオプションもあります。 React-Routerは、Routeコンポーネント内のRouterオブジェクトにアクセスするためにそれに依存します。私はすぐにcodepen上のコンテキストを使用した例をまとめ

:私は同様の質問に与えた別のanswerから

MainLayoutは、コンテキストを使用して子によって使用されるいくつかのプロパティを定義します:usersおよびwidgets。これらのプロパティは、UserListおよびWidgetListコンポーネントによって使用されます。彼らは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'))