React 路由器和 this.props.children - 如何将状态传递给 this.props.children
React router and this.props.children - how to pass state to this.props.children
我是第一次使用 React-router,我还不知道如何思考它。这是我在嵌套路由中加载组件的方式。
入口点.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>
);
}
所以我的应用程序的子项是我发送的内容组件。我正在使用 Flux,我的 App.js 有状态并监听变化,但我不知道如何传递该状态下降到 this.props.children。在使用 react-router 之前,我的 App.js 明确定义了所有子节点,因此传递状态是很自然的,但我现在不知道该怎么做。
这个问题归结为,如何将 props 传递给 children?
2018 年 6 月回答
今日科技:
- 反应 16+
- React Router 4:
react-router-dom
- Render Props from official docs
假设一些有状态的组件:
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>
)
我不再推荐我以前的老派答案:
使用几个 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>
}
然后你的 child 组件可以通过属性访问它,this.props.foo
。
您可以使用 React method "cloneElement" 来完成此操作。当你克隆元素时,你可以在那个时候传入 props。在渲染 fn 中使用克隆而不是原始文件。例如:
render: function() {
var childrenWithProps = React.cloneElement(this.props.children, {someProp: this.state.someProp});
return (
<div>
<Header />
{childrenWithProps}
</div>
);
}
还有使用 Context 的选项。 React-Router 依靠它来访问路由组件中的路由器 object。
来自另一个 answer 我提出了类似的问题:
我在 codepen 上使用上下文快速组合了一个示例。 MainLayout
定义了一些可以由 children 使用上下文使用的属性:users
和 widgets
。 UserList
和 WidgetList
组件使用这些属性。请注意,他们需要定义他们需要从 contextTypes
object.
中的上下文访问的内容
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'))
我是第一次使用 React-router,我还不知道如何思考它。这是我在嵌套路由中加载组件的方式。
入口点.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>
);
}
所以我的应用程序的子项是我发送的内容组件。我正在使用 Flux,我的 App.js 有状态并监听变化,但我不知道如何传递该状态下降到 this.props.children。在使用 react-router 之前,我的 App.js 明确定义了所有子节点,因此传递状态是很自然的,但我现在不知道该怎么做。
这个问题归结为,如何将 props 传递给 children?
2018 年 6 月回答
今日科技:
- 反应 16+
- React Router 4:
react-router-dom
- Render Props from official docs
假设一些有状态的组件:
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>
)
我不再推荐我以前的老派答案:
使用几个 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>
}
然后你的 child 组件可以通过属性访问它,this.props.foo
。
您可以使用 React method "cloneElement" 来完成此操作。当你克隆元素时,你可以在那个时候传入 props。在渲染 fn 中使用克隆而不是原始文件。例如:
render: function() {
var childrenWithProps = React.cloneElement(this.props.children, {someProp: this.state.someProp});
return (
<div>
<Header />
{childrenWithProps}
</div>
);
}
还有使用 Context 的选项。 React-Router 依靠它来访问路由组件中的路由器 object。
来自另一个 answer 我提出了类似的问题:
我在 codepen 上使用上下文快速组合了一个示例。 MainLayout
定义了一些可以由 children 使用上下文使用的属性:users
和 widgets
。 UserList
和 WidgetList
组件使用这些属性。请注意,他们需要定义他们需要从 contextTypes
object.
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'))