React router和this.props.children - 如何将状态传递给this.props.children

时间:2016-03-07 03:24:47

标签: reactjs react-router

我第一次使用React-router而且我还不知道如何思考它。这是我如何在嵌套路线中加载我的组件。

入口点.js

a[j] = x % 10

App.js

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

所以我的应用程序的孩子是我发送的内容组件。我使用Flux,我的App.js有状态并听取更改,但我不知道如何通过该状态直到this.props.children。在使用react-router之前,我的App.js明确地定义了所有孩子,所以传递状态很自然,但我现在不知道如何做。

3 个答案:

答案 0 :(得分:32)

这个问题可归结为, 如何将道具传递给儿童?

2018年6月回答

今天的科技:

假设有一些有状态的组件:

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

这是有效的,因为 this.props.children 是一个函数:

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

<强> Example on codesandbox

我以前的老学校回答我不再推荐了:

使用一些React辅助方法,您可以向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>
}

然后您的子组件可以通过道具this.props.foo访问它。

答案 1 :(得分:10)

您可以使用React method "cloneElement"来完成此操作。克隆元素时,可以在此时传递道具。在渲染fn中使用克隆而不是原始克隆。例如:

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

答案 2 :(得分:2)

还有使用Context的选项。 React-Router依赖它来访问路由组件中的Router对象。

我从另一个answer提出了一个类似的问题:

我在codepen上使用上下文快速汇总了一个示例。 MainLayout定义了一些可以由孩子使用上下文的属性:userswidgetsUserListWidgetList组件使用这些属性。请注意,他们需要从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'))