javascript - React-Router 在主组件和侧边栏组件之间传递 props

标签 javascript reactjs meteor react-router

我将 Meteor 与 React-Router 一起使用,并且我有以下代码:

Routes.jsx:

Meteor.startup(() => {
  render(
    <Router history={browserHistory}>
      <Route path='/' component={App}>
        <IndexRoute components={{ main: SelectTable, sidebar: MenuBar }} />
        <Route path='/DisplayTable/:tableId'
          components={{ main: DisplayTable, sidebar: MenuBar }} />
      </Route>
      <Route path='*' component={NotFound} />
    </Router>,
    document.getElementById('react-root'));
});

App.jsx:

export class App extends Component {
  render() {
    // if there's only one child logic here, irrelevant
    return (
      <div className='container'>
        <div className="Main">
          {this.props.main}
        </div>
        <div className="Sidebar">
          {this.props.sidebar}
        </div>
      </div>);
  }
}

我的 DisplayTable 组件监听对数据库的 Meteor 订阅并最终获取这些属性:

DisplayTable.propTypes = {
  tableId: PropTypes.string.isRequired,
  loading: PropTypes.bool.isRequired,
  rows: PropTypes.array.isRequired,
  cols: PropTypes.array.isRequired,
  user: PropTypes.object,
};

我的 MenuBar 组件呈现此:

<li><InsertRow tableId={this.props.params.tableId}/></li>

其中 InsertRow 具有这些属性

InsertRow.propTypes = {
  rows: PropTypes.array,
  tableId: PropTypes.string,
};

其中 InsertRowDisplayTable 的行属性完全相同。

如何将属性从主组件传递到侧边栏,以便我可以将其从那里传递到组件?

  • 也许是与 React.cloneElement 相关的东西,尽管我无法真正理解它......
  • 我已经查看了 mainsidebar 的所有属性,但似乎找不到任何有用的内容...

解决方法:

  • 理论上我可以订阅并再次获取数据,因为我有 tableId,但这似乎过于愚蠢,因为这两个组件实际上是在同一个路由中渲染的。
  • 我也可以在 MenuBar 上制作一个假 di​​v,并在显示表格时使用 jQuery 来替换它,但这似乎非常不 react 。
  • 我也可以为应用的 DisplayTable 部分制作另一个菜单,但我正在努力避免困惑。

(如果与答案相关,我不会使用React Router 4.0,而是使用最新版本的 meteor 3.0.5,尽管我猜这与此上下文无关)

编辑:我想我将在路径上方添加容器,这样我就已经有了数据。有点道理,但我会将其留在这里以防有人有更好的建议。

最佳答案

虽然可能有更好的方法来做到这一点,但我将在下面解释我最终做了什么:

Routes.jsx

Meteor.startup(() => {
  render(
    <Router history={browserHistory}>
      <Route path='/' component={App}> 
        //... like before

        <Route path='/DisplayTable' component={ Comp } >
          <Route path='/DisplayTable/:tableId'
            components={{ main: DisplayTable, sidebar: MenuBar }} />
        </Route>

      </Route>
      <Route path='*' component={NotFound} />
    </Router>,
    document.getElementById('react-root'));
});

然后我添加了组件布局Comp

Comp.jsx

class Comp extends Component {
  render() {
    // this is the final html for our table
    let displayTable = [];
    let menuBar = [];
    // while the data is loading, the html is a spinner
    if (this.props.loading) {
      displayTable.push(
        <div key='table-container' className='table-container table-container-no-data'>
          <div key='loading'>
            <span>Loading data...</span>
            <Spinner key='spinner' spinnerName='three-bounce' />
          </div>
        </div>);
    } else {
      // the Display Table properties
      displayTable = React.Children.map(this.props.main, child => React.cloneElement(child, {
        rows: this.props.rows,
        cols: this.props.cols,
      }));
      // the Menu Bar properties
      menuBar = React.Children.map(this.props.sidebar, child => React.cloneElement(child, {
        rows: this.props.rows,
        cols: this.props.cols,
      }));
    }

    return (
      <div className='container'>
        <div className="content">
          {displayTable}
        </div>
        <div className="menu">
          {menuBar}
        </div>
      </div>);
  }
}

Comp.propTypes = {
  loading: PropTypes.bool.isRequired,
  rows: PropTypes.array.isRequired,
  cols: PropTypes.array.isRequired,
  //... etc
};
/**
 * A Meteor createContainer component which retrieves data from Meteor & Mongo
 */
export default createContainer((props) => {
  // get the rows & cols by Meteor subscriptions here, as well as a loading to figure out when the subscription finished (this was originally in DisplayTable)
}

DisplayTable.jsx

DisplayTable.propTypes = {
  rows: PropTypes.array,
  cols: PropTypes.array,
};

(事实证明,与上面相反,这些就是我所需要的 - 在整个组件中使用它们,但基本上从 Comp 获取它们)

MenuBar.jsx

MenuBar.propTypes = {
  rows: PropTypes.array,
  cols: PropTypes.array,
};

(同上,调用InsertRow时使用它们)

菜单栏还调用InsertRow像这样:<li><InsertRow tableId={this.props.params.tableId} cols={this.props.cols} isDisabled={false} /></li>

关于javascript - React-Router 在主组件和侧边栏组件之间传递 props,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43649430/

相关文章:

javascript - Meteor - 模型继承

javascript - 在代理数组上调用 concat 会引发错误

javascript - 使用angularjs在ionic1中为http请求设置超时

reactjs - 如何将 AWS Elb 后面的 ReactJs SPA 的 http 重定向到 https?

javascript - 如何在 react 中保护身份验证背后的组件/路径?

meteor - 如何在 Meteor 的模板中做一些简单的数学运算?

javascript - 仅使用 Javascript 正则表达式匹配模式的最后一个实例

javascript - 多次调用 sagaMiddleware.run 是否安全?

javascript - 是否可以使用 React-strap 构建渐进式 Web 应用程序?

javascript - 从 Meteor 中的地理位置返回邮政编码