在何处以及如何异步请求数据以使用 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
部分作为道具传递给我的 IndexRoute
和 userpanel
路线。但是我不确定我应该怎么做。
想到几个问题:
- 我应该将异步数据请求放在代码中的其他地方吗?
- 我应该使用 React Router api(如
onEnter
)而不是 React 生命周期方法来获取数据吗?
- 如何将
App
的状态(用户)作为 props 传递给 Dashboard
和 UserPanel
组件?
- 我不确定如何使用
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 中的那些属性。请询问您是否有任何问题,因为这很令人困惑。
在阅读了很多关于这个主题的问题之后,我仍然不确定哪种是异步获取数据的最佳方式,这些数据稍后将作为道具传递给 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
部分作为道具传递给我的 IndexRoute
和 userpanel
路线。但是我不确定我应该怎么做。
想到几个问题:
- 我应该将异步数据请求放在代码中的其他地方吗?
- 我应该使用 React Router api(如
onEnter
)而不是 React 生命周期方法来获取数据吗? - 如何将
App
的状态(用户)作为 props 传递给Dashboard
和UserPanel
组件? - 我不确定如何使用
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 中的那些属性。请询问您是否有任何问题,因为这很令人困惑。