这是导致我麻烦的文件:
var Routers = React.createClass({
getInitialState: function(){
return{
userName: "",
relatives: []
}
},
userLoggedIn: function(userName, relatives){
this.setState({
userName: userName,
relatives: relatives,
})
},
render: function() {
return (
<Router history={browserHistory}>
<Route path="/" userLoggedIn={this.userLoggedIn} component={LogIn}/>
<Route path="feed" relatives={this.state.relatives} userName={this.state.userName} component={Feed}/>
</Router>
);
}
});
我正在尝试将新的this.state.relatives
和this.state.userName
通过路由传递到我的“Feed”组件中。但我收到此错误消息:
警告:[react-router]你无法改变;这将是 忽略
我知道为什么会发生这种情况,但不知道我应该如何将状态传递给我的“feed”组件。我一直试图在过去的5个小时内解决这个问题而且非常绝望!
请帮忙! 感谢
下面的答案很有帮助,我感谢他们,但他们并不是最简单的方法。 在我的案例中做到这一点的最好方法是: 当您更改路线时,您只需将消息附加到其中,如下所示:
browserHistory.push({pathname: '/pathname', state: {message: "hello, im a passed message!"}});
或者如果您通过链接执行此操作:
<Link
to={{
pathname: '/pathname',
state: { message: 'hello, im a passed message!' }
}}/>
来源:https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/location.md
在您尝试联系的组件中,您可以像这样访问变量,例如:
componentDidMount: function() {
var recievedMessage = this.props.location.state.message
},
我希望这有帮助! :)
答案 0 :(得分:26)
tl; dr 您最好的选择是在管理需要在整个应用程序中访问的状态时使用redux
或mobx
等商店。这些库允许您的组件连接/观察状态并保持最新的状态变化。
<Route>
?您无法通过<Route>
组件传递道具的原因是它们不是真正的组件,因为它们不会呈现任何内容。相反,它们用于构建路由配置对象。
这意味着:
<Router history={browserHistory}>
<Route path='/' component={App}>
<Route path='foo' component={Foo} />
</Route>
</Router>
相当于:
<Router history={browserHistory} routes={{
path: '/',
component: App,
childRoutes: [
{
path: 'foo',
component: Foo
}
]
}} />
路由仅在初始安装时进行评估,这就是您无法向其传递新道具的原因。
如果您要将某些静态道具传递到商店,则可以创建自己的高阶组件,将其注入商店。不幸的是,这仅适用于静态道具,因为如上所述,<Route>
仅被评估一次。
function withProps(Component, props) {
return function(matchProps) {
return <Component {...props} {...matchProps} />
}
}
class MyApp extends React.Component {
render() {
return (
<Router history={browserHistory}>
<Route path='/' component={App}>
<Route path='foo' component={withProps(Foo, { test: 'ing' })} />
</Route>
</Router>
)
}
}
location.state
location.state
是在导航时在组件之间传递状态的便捷方式。然而,它有一个主要的缺点,即只有在您的应用程序中导航时才存在状态。如果用户关注指向您网站的链接,则该位置不会附加任何州。
那么如何将数据传递到您的路由component
?一种常见的方法是使用redux
或mobx
等商店。使用redux
,您可以使用更高阶的组件将connect
组件发送到商店。然后,当您的路线component
(实际上是您的路线组件作为其子路径的HOC)呈现时,它可以从商店获取最新信息。
const Foo = (props) => (
<div>{props.username}</div>
)
function mapStateToProps(state) {
return {
value: state.username
};
}
export default connect(mapStateToProps)(Foo)
我对mobx
并不是特别熟悉,但根据我的理解,它可以更容易设置。使用redux
,mobx
或其他状态管理是在整个应用程序中传递状态的好方法。
注意:您可以在这里停止阅读。以下是传递状态的合理示例,但您应该只使用商店库。
如果您不想使用商店怎么办?你运气不好吗?不,但您必须使用React的实验性功能:context
。要使用context
,您的一个父组件必须明确定义getChildContext
方法以及childContextTypes
对象。任何想要通过context
访问这些值的子组件都需要定义contextTypes
对象(类似于propTypes
)。
class MyApp extends React.Component {
getChildContext() {
return {
username: this.state.username
}
}
}
MyApp.childContextTypes = {
username: React.PropTypes.object
}
const Foo = (props, context) => (
<div>{context.username}</div>
)
Foo.contextTypes = {
username: React.PropTypes.object
}
您甚至可以编写自己的高阶组件,自动将context
值作为<Route>
component
的道具。这将是一个穷人的商店&#34;。您可以使用它,但与使用上述商店库之一相比,可能效率更低,错误更多。
React.cloneElement
怎么样?还有另一种方法可以为<Route>
component
提供道具,但它一次只能运行一个级别。实质上,当React Router基于当前路由渲染组件时,它首先为最深嵌套的匹配<Route>
创建一个元素。然后,在为下一个嵌套最深的children
创建元素时,它会将该元素作为<Route>
道具传递。这意味着在第二个组件的render
方法中,您可以使用React.cloneElement
克隆现有的children
元素,并为其添加其他道具。
const Bar = (props) => (
<div>These are my props: {JSON.stringify(props)}</div>
)
const Foo = (props) => (
<div>
This is my child: {
props.children && React.cloneElement(props.children, { username: props.username })
}
</div>
)
这当然是单调乏味的,特别是如果您需要通过<Route>
component
的多个级别传递此信息。您还需要在基本<Route>
组件(即<Route path='/' component={Base}>
)内管理您的状态,因为您无法从<Router>
的父组件中注入状态。
答案 1 :(得分:1)
安装路由器组件后,无法更改React-router的状态。您可以编写自己的HTML5路由组件并监听网址更改。
class MyRouter extend React.component {
constructor(props,context){
super(props,context);
this._registerHashEvent = this._registerHashEvent.bind(this)
}
_registerHashEvent() {
window.addEventListener("hashchange", this._hashHandler.bind(this), false);
}
...
...
render(){
return ( <div> <RouteComponent /> </div>)
}
答案 2 :(得分:0)
我知道回答这个问题可能为时已晚,但是对于以后对此有所疑问的任何人,您都可以采用以下示例方式:
export default class Routes extends Component {
constructor(props) {
super(props);
this.state = { config: 'http://localhost' };
}
render() {
return (
<div>
<BrowserRouter>
<Switch>
<Route path="/" exact component={App} />
<Route path="/lectures" exact render={() => <Lectures config={this.state.config} />} />
</Switch>
</BrowserRouter>
</div>
);
}
}
这样,您可以在Lecture组件内访问配置道具。 这是一个围绕该问题的步骤,但是从一开始它就是一个不错的选择! :)
答案 3 :(得分:0)
对于像我这样的人
您通常也可以渲染此:
import {
BrowserRouter as Router,
Router,
Link,
Switch
} from 'react-router-dom'
<Router>
<Switch>
<Link to='profile'>Profile</Link>
<Route path='profile'>
<Profile data={this.state.username} />
</Route>
<Route component={PageNotFound} />
</Switch>
</Router>
这对我有用!
答案 4 :(得分:0)
请注意,如果您使用的是 query string
,则需要添加 search
。
例如:
{
key: 'ac3df4', // not with HashHistory!
pathname: '/somewhere',
search: '?some=search-string',
hash: '#howdy',
state: {
[userDefined]: true
}
}
花了大约 20 分钟才弄清楚为什么我的路线没有被渲染 ?