Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 如何将状态从路由器传递到子组件_Reactjs_React Router - Fatal编程技术网

Reactjs 如何将状态从路由器传递到子组件

Reactjs 如何将状态从路由器传递到子组件,reactjs,react-router,Reactjs,React Router,我正在使用react路由器2.0.0。考虑下面的例子: import React from 'react'; import ReactDOM from 'react-dom'; import { Router, Route, IndexRoute, hashHistory } from 'react-router'; const Main = React.createClass({ getInitialState() { re

我正在使用react路由器2.0.0。考虑下面的例子:

 import React from 'react';
    import ReactDOM from 'react-dom';

    import { Router, Route, IndexRoute, hashHistory } from 'react-router';

    const Main = React.createClass({
        getInitialState() {
            return {data: 0};
        },
        componentDidMount() {
            setInterval(() => {
                console.log("Imagine I am polling data from a server here");
                this.setState({data: Math.random().toFixed(2)});
            }, 2000);
        },
        render() {
            return <Router history={hashHistory}>
                <Route path="/">
                    <IndexRoute component={MainPage} data={this.state.data}/>
                    <Route path="page1" component={Page1} data={this.state.data}/>
                </Route>
            </Router>;
        }
    });
    const MainPage = React.createClass({
        render() {
            return <div>MainPage, data: {this.props.route.data}</div>;
        }
    });
    const Page1 = React.createClass({
        render() {
            return <div>Page1, data: {this.props.route.data}</div>;
        }
    });

    ReactDOM.render(<Main />, document.getElementById('app'));
从“React”导入React;
从“react dom”导入react dom;
从“react Router”导入{Router,Route,IndexRoute,hashHistory};
const Main=React.createClass({
getInitialState(){
返回{数据:0};
},
componentDidMount(){
设置间隔(()=>{
log(“假设我正在从这里的服务器轮询数据”);
this.setState({data:Math.random().toFixed(2)});
}, 2000);
},
render(){
返回
;
}
});
const MainPage=React.createClass({
render(){
返回主页面,数据:{this.props.route.data};
}
});
const Page1=React.createClass({
render(){
返回第1页,数据:{this.props.route.data};
}
});
ReactDOM.render(,document.getElementById('app'));
我对react.js的理解是,数据通常应该作为道具传递给子组件。 在本例中,我正在轮询来自服务器的一些数据,这些数据应该由两个不同的子组件使用。因为它是动态数据,所以我将它置于状态

然而,若我在同一个组件中定义了路由,react路由器就会崩溃,因为它会被重新渲染。更新的状态不会传递给子级,控制台将打印:

Imagine I am polling data from a server here
Warning: [react-router] You cannot change <Router routes>; it will be ignored
假设我正在从服务器轮询数据
警告:[反应路由器]您无法更改;它将被忽略
我不喜欢的一种解决方法是使用全局状态来访问数据。我就是这么做的


这个用例有一个优雅的解决方案吗?

选项1:Facebook提供了一种通过使用


我很快用上下文将一个例子放在一起
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'))
然后,在作为子路由一部分的所有组件中,它们将自动获得这些属性,并且可以通过它们的
道具
访问这些属性

例如,在中,
Admin
是父组件,请检查其

如中所示,位于
/admin
下的子路由中的组件是
PostList
PostList
正在使用来自
Admin
的函数
getAdminPost


我建议您在单独的文件中定义路由,如中所述。

让我将该解决方案转移到我的示例中:我将引入一个新组件,如:
。将数据存储在其状态,并使其通过您描述的
cloneElement
内容传播数据更新。嗯,很有趣,至少这避免了全球状态,但感觉真的很不舒服。这就像手动执行react.js应该处理的状态道具更新一样。此外,道具传递实际上隐藏在
DataComponent
中。在HTML中将其显式地作为属性更容易掌握。我同意这也不是一个很好的解决方案。现在,我想起来了,我记得我在看,只是我不记得为什么我没有使用它们,并决定去解决这个问题。上下文是这样做的官方解决方案,但他们不建议滥用它。理想情况下,如果您知道您的子组件,您只需将属性作为属性传递给它们。作为属性传递实际上不起作用,这就是我的示例所做的。当你有状态的时候它就不起作用了,因为当它被重新渲染的时候路由器会断开
MainLayout
定义了一些可由使用上下文的子级使用的属性:
users
widgets
。这些属性由
UserList
WidgetList
组件使用。注意,他们需要从代码中的上下文中定义他们需要访问的内容。虽然脸谱网认为上下文是实验性的,但是<代码>反应路由器项目严重依赖于它。无论何时,只要您想以编程方式导航到路由,就需要访问路由器对象,这可以通过上下文完成:
{this.props.children && React.cloneElement(this.props.children, {
   prop1: this.props.prop1,
   prop2: this.props.prop2
})}