React-Router 1.0.0RC1 - 将状态作为属性传递给子路由

时间:2015-10-02 12:51:58

标签: javascript reactjs react-router react-router-component

我正在使用Alex Bank's "Building a Polling App with Socket IO and React.js" (Lynda.com),但我正在尝试将其升级到react-router 1.0.0-RC1。

  

以下解决方案,只需跳过所有

请不要发给我文件,这对我不起作用,我想我必须太厚才能理解文档中的“简洁”。

我有一个主要的APP有3条儿童路线,(受众,演讲者和董事会)。

到目前为止我的代码:

APP.js

import React, { Component } from 'react';
import io from 'socket.io-client';
import Header from './parts/Header';
import Routes from '../router/routes';
import { createHistory, useBasename } from 'history';

const history = useBasename(createHistory)({
  basename: '/'
});

export default class APP extends Component {

  constructor() {
    super();
    this.state = ({
      status: 'disconnected',
      title: ''
    });
  }

  componentWillMount() {
    this.socket = io('http://localhost:3000');
    this.socket.on('connect', this.connect.bind(this));
    this.socket.on('disconnect', this.disconnect.bind(this));
    this.socket.on('welcome', this.welcome.bind(this));
  }

 connect() {
    this.setState({status: 'connected'});
 }

 disconnect() {
    this.setState({status: 'disconnected'});
 }

 welcome(serverState) {
    this.setState({title: serverState.title});
 }

render() {
   return (
     <div>
       <Header title={ this.state.title } status={ this.state.status }/>
       { /* I WANT TO PASS THIS.STATE.STATUS TO CHILD ROUTES  */}
       <Routes history={ history } />
     </div>
    );
  }
}

Routes.js

import React, { Component } from 'react';
import Route from 'react-router';
import APP from '../components/APP';
import Audience from '../components/Audience';
import Board from '../components/Board';
import Speaker from '../components/Speaker';
import NotFound from '../components/NotFound';


export default class Routes extends Component {
  constructor() {
    super();
  }

  render() {
    return (
      <Route history={ this.props.history } component={ APP }>
        <Route path="/" component={ Audience } />
        <Route path="audience" component={ Audience } />
        <Route path="board" component={ Board } />
        <Route path="speaker" component={ Speaker } />
        <Route path="*" component={ NotFound } />
      </Route>
    );
  }
}

Audience.js

import React, { Component } from 'react';

export default class Audience extends Component {

 constructor() {
   super();
 }


 render() {
   return (
     <div>
      Audience - STUCK HERE!! - How to pass APP's this.state.status as a prop????        
     </div>
   );
 }

}

虽然应用程序运行,并且我已阅读文档,但仍无法将APP的this.state.status作为属性传递给Audience应用程序。

我已经在这2天没有用,但它变得令人沮丧。 TGIF。

  

期望的结果:

     

当浏览器打开到localhost:3000时,默认页面   (Audience.js),读作:

 Untitled Presentation - connected

 Audience - connected
     

我无法将连接状态传递给Audience组件,因此   “连接”字样未显示在“受众”旁边。我是连接的,正如Header的“Untitled Presentation - connected”

所证明的那样

有人可以在这里帮助我。

非常感谢!

2 个答案:

答案 0 :(得分:1)

APP组件中,您需要包含以下内容:

{React.cloneElement(this.props.children, {status: this.state.status })}

然后在audience组件中,您将this.props.status提供该组件。

修改

我刚注意到你有一个循环依赖。我建议摆脱它,以便依赖只在一个方向:

routes.js --> app.js --> audience.js

看看这个example。这可以通过提取两个React类分解为三个文件:

  1. main.js这会呈现路线
  2. App.js这会呈现应用并包含子路由
  3. Taco.js这就是taco。
  4. 然后可以表示如下:

        main.js --> App.js --> Taco.js
    

答案 1 :(得分:0)

  

<强> SOLUTION:

正如Clarkie所提到的,我确实有循环依赖性,因为我正在遵循使用react-router 0.13并将APP作为入口点的传统设置。

此问题的大部分帮助来自cluster pattern

  

悲伤&#39;无法找到详细的帮助   直接来自react-router文档。

我的新切入点现在是:

<强> Index.js

import React from 'react';
import ReactDOM from 'react-dom';
import Router from 'react-router';
import createBrowserHistory from 'history/lib/createBrowserHistory';

  const routerProps = {
    routes: require('./router/routes'),
    history: createBrowserHistory(),
    createElement: (component, props) => {
      return React.createElement(component, { ...props});
    }
  };

  ReactDOM.render(
    React.createElement(Router, { ...routerProps }),
    document.getElementById('root')
  );

<强> Routes.js:

  

注意:我特别喜欢他们的路线,因为我能看到相当    清楚地知道如何为大型应用转变这种动态(来自Db的数据)。

import React from 'react';
import { Route } from 'react-router';
import { generateRoute } from '../utils/localized-routes';

export default (
  <Route component={ require('../components/APP') }>
    { generateRoute({
      paths: ['/', '/audience'],
      component: require('../components/Audience')
    }) }
    { generateRoute({
      paths: ['/speaker'],
      component: require('../components/Speaker')
    }) }
    { generateRoute({
      paths: ['board'],
      component: require('../components/Board')
    }) }
    <Route path="*" component={ require('../components/NotFound') } />
  </Route>
);

<强>局部-routes.js:

import React from 'react';
import { Route } from 'react-router';

export function generateRoute({ paths, component }) {
  return paths.map(function(path) {
    const props = { key: path, path, component };
    // Static `onEnter` is defined on
    // component, we should pass it to route props
    if (component.onEnter) props.onEnter = component.onEnter;
    return <Route {...props} />;
  });
}

// SWEET!!! Nice touch.
export function replaceParams(route, params) {
  let parsedRoute = route.trim();
  Object.keys(params).forEach(function(paramKey) {
    const param = ':' + paramKey;
    const paramValue = params[paramKey];
    if (parsedRoute && parsedRoute.match(param)) {
      parsedRoute = parsedRoute.replace(param, paramValue);
    }
  });
  return parsedRoute;
}

<强> APP.js:

import React, { Component, PropTypes } from 'react';
import io from 'socket.io-client';
import Header from './parts/Header';

export default class APP extends Component {
  static propTypes = {
    children: PropTypes.element
  }

  constructor(props, context) {
   super(props, context);
   this.state = ({
    status: 'disconnected',
    title: ''
  });
 }

 componentWillMount() {
  this.socket = io('http://localhost:3000');
  this.socket.on('connect', this.connect.bind(this));
  this.socket.on('disconnect', this.disconnect.bind(this));
  this.socket.on('welcome', this.welcome.bind(this));
}

 connect() {
   this.setState({ status: 'connected' });
}

 disconnect() {
   this.setState({ status: 'disconnected' });
}

 welcome(serverState) {
   this.setState({ title: serverState.title });
}

 renderChild = () =>
   React.cloneElement(this.props.children, { status: this.state.status });

 render() {
   return (
      <div>
         <Header title={ this.state.title } status={ this.state.status }/>
        { React.Children.map(this.props.children, this.renderChild) }
      </div>
    );
  }
}

<强> Audience.js:

import React, { Component } from 'react';
import Display from './Display';

export default class Audience extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div>
       Audience - { this.props.status }
        <Display if={ this.props.status === 'connected' }>
          <h1>Join the session</h1>
        </Display>
      </div>
     );
   }
 }

<强> Display.js:

import React, { Component } from 'react';

export default class Display extends Component {
  render() {
    return (
        <div>
        { this.props.if ? <div> { this.props.children } </div> : null }
        </div>
        );
    }
}
  

期望的结果:

iam4x/isomorphic-flux-boilerplate