反应路由器和 this.props.children - 如何将状态传递给 this.props.children
Posted
技术标签:
【中文标题】反应路由器和 this.props.children - 如何将状态传递给 this.props.children【英文标题】:React router and this.props.children - how to pass state to this.props.children 【发布时间】:2016-06-20 12:38:45 【问题描述】:我是第一次使用 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>
);
所以我的 App 的子组件是我发送的 Content 组件。我正在使用 Flux 并且我的 App.js 具有状态并侦听更改,但我不知道如何将该状态传递给它。道具.儿童。在使用 react-router 之前,我的 App.js 明确定义了所有子节点,因此传递状态很自然,但我现在不知道该怎么做。
【问题讨论】:
How to pass props to this.props.children的可能重复 【参考方案1】:这个问题归结为,你如何将道具传递给孩子?
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>
)
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>
然后你的子组件可以通过 props 访问它,this.props.foo
。
【讨论】:
是的,我在阅读有关儿童帮手的信息时看到了这个。为什么要使用 Map 而不是 ForEach? 如果你能提供帮助,一般建议不要改变数据。这是一般编程中的好习惯,不仅适用于 React。只有在没有其他可能的解决方案时才进行突变——这种情况很少见。 我同意突变,但我想我没有看到联系 - ForEach 是否一定会突变状态? 好吧cloneElement
返回一个新的子对象,所以你需要返回一个新的children
数组/对象。 Children.forEach
不返回任何内容,Array.prototype.forEach
也不返回。如果您不返回任何内容,则不会影响任何更改,除非您改变某些内容或引起副作用(保存到数据库/进行 ajax 调用等)
感谢您的回答,就像一个魅力。但是,我收到来自子组件的 propType 验证警告,说道具未定义。我可以毫无问题地使用它们,但我不知道为什么会抛出这些警告?你有什么想法吗?【参考方案2】:
您可以使用React method "cloneElement" 来完成此操作。当你克隆元素时,你可以在那个时候传入道具。在渲染 fn 中使用克隆而不是原始。例如:
render: function()
var childrenWithProps = React.cloneElement(this.props.children, someProp: this.state.someProp);
return (
<div>
<Header />
childrenWithProps
</div>
);
【讨论】:
childrenWithProps
周围缺少花括号
在 this.props.children 只有一个元素的情况下,您的示例会克隆所有孩子还是只克隆一个?我在 *** 上看到了另一个示例,但我需要手动遍历它们只是为了传递基本的道具,这似乎是错误的。
@Patrick 如果您查看我的回答,您会首先注意到Children.map
。这是必需的,通常是因为children
可以是对象或数组,在后一种情况下,您需要克隆每个元素。
@Patrick 正如@azium 所说,我的示例仅在this.props.children
是单个对象而不是数组时才有效。而且,Children.map
将起作用,即使 this.props.children
是单个对象。所以他们的建议比我的更好。
谢谢!我很高兴得到帮助【参考方案3】:
还可以选择使用Context。 React-Router 依赖它来访问路由组件中的 Router 对象。
来自另一个answer 我提出了一个类似的问题:
我在codepen 上快速整理了一个使用上下文的示例。 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'))
【讨论】:
以上是关于反应路由器和 this.props.children - 如何将状态传递给 this.props.children的主要内容,如果未能解决你的问题,请参考以下文章