我是 React 的新手,在使用 getComponent 加载路径时,我无法弄清楚如何渲染“loading ...”屏幕。 getComponent 调用正常工作并显示组件,但 UI 上没有任何迹象表明请求和响应之间发生了任何事情。这就是我想弄清楚的。
import Main from './pages/Main.jsx';
import Test from './pages/Test.jsx';
import Home from './pages/Home.jsx';
var Routes = {
path: "/",
component: Main,
indexRoute: {
component: Home
},
childRoutes: [
{
path: "test",
component: Test
},
{
path: "about",
getComponent: function(path, cb) {
require.ensure([], (require) => {
cb(null, require("./pages/about/About.jsx"));
});
}
}
]
};
export default Routes;
在尝试使用 onEnter 或 getComponent 函数强制“加载”组件显示失败后,我想也许我应该尝试使用 Redux 将加载状态设置为 true/false 并让我的主视图组件显示加载屏幕:
import React from 'react';
import {connect} from 'react-redux';
import NavBar from '../components/Navigation/NavBar.jsx';
import Footer from '../components/Footer.jsx';
import Loading from './Loading.jsx';
import navItems from '../config/navItems.jsx';
import setLoading from '../actions/Loading.jsx';
var Main = React.createClass({
renderPage: function() {
if (this.props.loading) {
return (
<Loading/>
);
} else {
return this.props.children;
}
},
render: function() {
return (
<div>
<header id="main-header">
<NavBar navigation={navItems}/>
</header>
<section id="main-section">
{this.renderPage()}
</section>
<Footer id="main-footer" />
</div>
);
}
});
function mapStateToProps(state) {
return {
loading: state.loading
}
}
export default connect(mapStateToProps)(Main);
如果我使用动作手动设置加载状态,这似乎有效,这是我想要做的。但是(我觉得这将是一个真正的 noob 问题)我无法弄清楚如何从路由器中访问 store/dispatcher。
我不确定我是否使用了错误的搜索术语或者其他什么,但我完全没有想法,而且每个 react-router/redux 教程似乎都跳过了我认为必须成为常见问题的东西。
任何人都可以指出我正确的方向(也让我知道我正在做什么是最好的做法?)?
编辑:我会尝试澄清这一点。在第一个代码块中,您可以看到如果单击<Link to="/about">
元素,则将触发 getComponent 函数,这将 lazy-load About.jsx 组件。我遇到的问题是我无法弄清楚如何显示某种加载 indicator/spinner,它会在点击链接后立即显示,然后在组件加载后立即更换。
更多编辑:我已经尝试创建一个包装器组件来加载异步路由,它似乎工作,但它感觉真的很 hacky,我敢肯定这不是正确的方法去做这件事。路由代码现在看起来像这样:
import Main from './pages/Main.jsx';
import Test from './pages/Test.jsx';
import Home from './pages/Home.jsx';
import AsyncRoute from './pages/AsyncRoute.jsx';
var Routes = {
path: "/",
component: Main,
indexRoute: {
component: Home
},
childRoutes: [
{
path: "test",
component: Test
},
{
path: "about",
component: AsyncRoute("about")
}
]
};
export default Routes;
AsyncRoute.jsx 页面如下所示:
import React from 'react';
function getRoute(route, component) {
switch(route) {
// add each route in here
case "about":
require.ensure([], (require) => {
component.Page = require("./about/About.jsx");
component.setState({loading: false});
});
break;
}
}
var AsyncRoute = function(route) {
return React.createClass({
getInitialState: function() {
return {
loading: true
}
},
componentWillMount: function() {
getRoute(route, this);
},
render: function() {
if (this.state.loading) {
return (
<div>Loading...</div>
);
} else {
return (
<this.Page/>
);
}
}
});
};
export default AsyncRoute;
如果有人有更好的想法,请告诉我。
4 回答
我想我已经搞清楚了。它可能是也可能不是正确的方法,但似乎有效。我也不知道为什么我之前没有想到这一点。
首先,将我的 createStore 代码移动到它自己的文件(store.jsx),这样我就可以将它导入主入口点以及我的 Routes.jsx 文件:
Root.jsx 看起来像这样(这是一个丑陋的混乱,但我只是想尝试在基本级别上运行的东西,然后我会清理它):
我已经制作了一个显示 Loading/Loaded 的基本组件,具体取决于 Redux 商店的“加载”值:
现在我的 Routes.jsx 文件看起来像这样(注意我已经导入了 Redux 商店):
这似乎有效。只要单击
<Link/>
转到/about 路径,就会调度操作以在主存储中将“加载”状态设置为 true。这导致<Loading/>
组件自行更新(我设想它最终会在窗口的角落或类似的东西中渲染一个微调器)。运行奇怪的require.ensure([])
函数以使 webpack 执行其奇特的代码拆分,并且一旦加载了组件,就会调度另一个操作以将加载状态设置为 false,并呈现组件。我仍然是 React 的新手,虽然这似乎有用,但我不确定这是否是正确的方法。如果有人有更好的方法,请加入!
按照相同的方法 as_1_M 我实现了一个加载减速器和一个包装调度的函数。
不包括商店创建和管理,它们基本上如下:
loadingReducer:
注意对于嵌套路由,
loadingQueue
如何保持加载消息处于活动状态,同时还有剩余要获取的模块。withLoader功能:
现在,在定义新路由时,我们可以使用 withLoader 隐式调度加载操作:
someRoute:
好的,让我们看看我是否可以对此有所了解:
没有必要那样做 AFAIK。您可以指定所有路由,列出应回答每个路由的组件(如上所述),然后将每个组件连接到 redux 存储。对于连接,您的
mapStateToProps
函数可以用更简单的方式编写,如下所示:关于
loading
状态:我认为这是一个错误的方向,有一个 slow-loading 组件,并在加载时显示一个等待指示器。我宁愿有一个 fast-loading 组件从后端异步加载它的所有数据,虽然数据还没有,但组件呈现一个等待指示器。数据可用后,即可显示。这基本上就是你在第二次编辑中描绘的内容。如果你能从实际数据中推出这个数据会更好,i.e。没有数据 - >显示加载屏幕/数据存在 - >显示真实屏幕。这样,您可以避免在加载标志不同步时出现问题。 (从技术上讲:避免 redundancy.)
因此,我宁愿为加载屏幕创建一个独立的组件,而不是让包装器变得通用,而是在每个单独的组件都需要时显示它。 (这些需求是不同的,所以似乎很难在通用 way.)这样的事情中处理这个:
动态加载异步路由器正在使用
require.ensure
,它使用jsonp从网络下载脚本。由于网络速度慢,有时 UI 块,屏幕仍显示预览反应组件。@Nicole ,真的很慢不是组件内部的数据加载,而是组件 self,因为 jsonp