在何处以及如何异步请求数据以使用 React Router (v 1) 作为 props 向下传递

Where and How to request data asynchronously to be passed down as props with React Router (v 1)

在阅读了很多关于这个主题的问题之后,我仍然不确定哪种是异步获取数据的最佳方式,这些数据稍后将作为道具传递给 React Router v1.0.0 及更高版本的子路由。

我的路由配置如下所示:

import { render } from 'react-dom';
// more imports ...

...

render(
  <Router>
  <Route path="/" component={App} />
    <IndexRoute component={Dashboard}/>
    <Route path="userpanel" component={UserPanel}/>
  </Router>,
  document.getElementById('container')
)

在我的 App 组件中,我有代码从后端异步获取数据,如果获取成功,它将把它合并到它的状态中。我在 App.

中使用 componentDidMount

App 的状态看起来像这个人为的例子:

{
  user: {
    name: 'Mike Smith',
    email: 'mike@smith.com'
  }
}

我想将状态的 user 部分作为道具传递给我的 IndexRouteuserpanel 路线。但是我不确定我应该怎么做。

想到几个问题:

  1. 我应该将异步数据请求放在代码中的其他地方吗?
  2. 我应该使用 React Router api(如 onEnter)而不是 React 生命周期方法来获取数据吗?
  3. 如何将 App 的状态(用户)作为 props 传递给 DashboardUserPanel 组件?
  4. 我不确定如何使用 React.cloneElement 执行此操作,如其他答案所示。

提前感谢您的帮助。

你可以在应用程序启动时做一件事,那时你将调用 API 并获取数据并注册你的路由,例如 我的 index.js 是入口文件然后

这里我使用了React-Router 0.13.3你可以根据新路由器

更改语法
fetchData(config.url+'/Tasks.json?TenantId='+config.TenantId).then(function(items)
{
    var TaskData=JSON.parse(JSON.stringify(items.json.Tasks));
    var Data=[];
    Object.keys(TaskData).map(function(task){
        if(TaskData[task].PageName !=='' && TaskData[task].PageUrl !=='')
        {
            Data.push({PageName:TaskData[task].PageName,path:TaskData[task].PageName+'/?:RelationId',PageUrl:TaskData[task].PageUrl});
        }
    });

    Data.push({PageName:'ContainerPage',path:'/ContainerPage/?:RelationId',PageUrl:'./pages/ContainerPage'});

    var routes=require('./routes')(Data);
    $("#root").empty();
    Router.run(routes,function(Handler){
        React.render(<Handler />,document.getElementById('root'));
    });

    React.render(<UserRoles />, document.getElementById("userrole"));
}).catch(function(response)
{
    showError(response);
});

我已将数据传递到 routes.js 文件,如 var routes=require('./routes')(Data);,我的 routes.js 文件如

export default (data =>
  <Route name="App" path="/" handler={App}>
    <NotFoundRoute handler={require('./pages/PageNotFound')} />
    <Route handler={TaskList} data={data} >
    </Route>
{ data.map(task =>
  <Route name={task.PageName} path={task.path}  handler={require(task.PageUrl)}>
  </Route>
    ) }
</Route>
);

您要求的是路由之间的持久数据,这不是路由器的工作。

您应该创建一个存储(以通量术语),或一个 model/collection(以 MVC 术语)——反应的通常方法是 flux-like。我推荐 redux.

在 redux 文档中它有一个 example 获取一个 reddit 用户:

componentDidMount() {
  const { dispatch, selectedReddit } = this.props
  dispatch(fetchPostsIfNeeded(selectedReddit))
}

我个人认为 flux/redux 不是 实现 的最简单方法,但它的扩展性很好。基本概念是即使你决定使用其他东西:

  • 你是对的,因为 Facebook suggests,异步抓取在 componentDidMount 中表现最好。

If you want to integrate with other JavaScript frameworks, set timers using setTimeout or setInterval, or send AJAX requests, perform those operations in this method.

  • 接下来您需要在 store/model 中设置此数据,可以从其他组件访问该数据。

redux(使用 react-redux)的好处在于,对于每个组件,您可以说 "Here are the actions this component is interested in",然后该组件可以简单地调用 UserActions.fetchUserIfNeeded() 之类的操作,操作将弄清楚它是否已经有用户或者是否应该获取它,然后它将 re-render 并且道具将可用。

问题 4 的答案:您要克隆什么?为什么?如果是 child,请参阅

我不完全确定我理解这个问题,但我最近也将属性传递给了我的路线的 children。如果这不是最好的方法,请原谅我,但您必须克隆 children 并编辑它们,然后传递副本而不是 children。我不确定为什么反应和反应路由器会让你这样做,但试试这个:
let children (or whatever you want to name it) = React.Children.map(this.props.children, (child) => { return React.cloneElement(child, {name of property: property value}); }); 之后,您应该能够在子路由中访问 this.props 中的那些属性。请询问您是否有任何问题,因为这很令人困惑。