在react-router中调用getComponent时如何显示加载UI?

2024-01-03

我对 React 很陌生,我不知道如何在使用 getComponent 加载路由时呈现“正在加载...”屏幕。 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);

如果我使用操作手动设置加载状态,这似乎有效,这正是我想要做的。但是(我觉得这将是一个真正的菜鸟问题)我无法弄清楚如何从路由器内访问商店/调度程序。

我不确定我是否使用了错误的搜索词或其他什么,但我完全没有想法,每个react-router/redux教程似乎都跳过了我认为必须是一个常见问题的问题。

谁能指出我正确的方向(并让我知道我所做的是否是最佳实践?)?

EDIT: 我会尝试进一步澄清这一点。在第一个代码块中,您可以看到如果我单击<Link to="/about">元素,然后 getComponent 函数将触发,这将延迟加载 About.jsx 组件。我遇到的问题是我无法弄清楚如何显示某种加载指示器/旋转器,这些指示器/旋转器在单击链接后立即出现,然后在组件加载后将其替换。

更多编辑:我尝试创建一个包装器组件来加载异步路由,它似乎可以工作,但是感觉真的很老套,我确信这不是执行此操作的正确方法。路由代码现在看起来像这样:

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;

如果有人有更好的主意,请告诉我。


我想我已经弄清楚了。这可能是也可能不是正确的处理方式,但它似乎有效。我也不知道为什么我没有早点想到这一点。

首先,将我的 createStore 代码移至其自己的文件 (store.jsx),以便我可以将其导入到主入口点以及我的 Routes.jsx 文件中:

import {createStore} from 'redux';
import rootReducer from '../reducers/Root.jsx';

var store = createStore(rootReducer);

export default store;

Root.jsx 看起来像这样(这是一个丑陋的混乱,但我只是想得到一些在基本层面上工作的东西,然后我会清理它):

import {combineReducers} from 'redux';
import user from './User.jsx';
import test from './Test.jsx';

var loading = function(state = false, action) {
  switch (action.type) {
    case "load":
      return true;
    case "stop":
      return false;
    default:
      return state;
  }
};


export default combineReducers({
  user,
  test,
  loading
});

我制作了一个基本组件,根据 Redux 存储的“正在加载”值显示正在加载/已加载:

import React from 'react';
import {connect} from 'react-redux';

var Loading = React.createClass({
  render: function() {
    if (this.props.loading) {
      return (
        <h1>Loading</h1>
      );
    } else {
      return (
        <h1>Loaded</h1>
      );
    }
  }
});

export default connect(state => state)(Loading);

现在我的 Routes.jsx 文件如下所示(注意我已经导入了 Redux 存储):

import Main from './pages/Main.jsx';
import Test from './pages/Test.jsx';
import Home from './pages/Home.jsx';
import store from './config/store.jsx';

var Routes = {
  path: "/",
  component: Main,
  indexRoute: {
    component: Home
  },
  childRoutes: [
    {
      path: "test",
      component: Test
    },
    {
      path: "about",
      getComponent: function(path, cb) {
        store.dispatch({type: "load"})
        require.ensure([], (require) => {
          store.dispatch({type: "stop"});
          cb(null, require("./pages/about/About.jsx"));
        });
      }
    }
  ]
};

export default Routes;

这似乎有效。一旦<Link/>单击以转到 /about 路线,将调度一个操作以将主商店中的“正在加载”状态设置为 true。这导致<Loading/>组件来更新自身(我想象它最终会在窗口的角落呈现一个旋转器或类似的东西)。那个奇怪的require.ensure([])运行函数来让 webpack 进行其奇特的代码分割,一旦组件被加载,就会调度另一个操作来将加载状态设置为 false,并渲染组件。

我对 React 还很陌生,虽然这似乎有效,但我不确定这是否是正确的方法。如果谁有更好的方法,欢迎留言!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在react-router中调用getComponent时如何显示加载UI? 的相关文章

随机推荐

  • 将 contentViewController 设置为 NSTabViewController 后,NSWindow 启动时大小错误

    我有一个 Xcode 项目NSWindowController whose contentViewController被设置为子类NSViewController 我最近删除了NSViewController从故事板子类并替换content
  • RequireJS:如何定义包含单个“类”的模块?

    我有许多 JavaScript 类 每个类都在自己的 JavaScript 文件中实现 对于开发 这些文件是单独加载的 对于生产 它们是串联的 但在这两种情况下 我都必须手动定义加载顺序 确保如果 B 使用 A 则 B 在 A 之后 我打算
  • Ninject 属性注入返回 null

    我有一个 WinForms 应用程序 代码如下 static void Main IKernel kernel new StandardKernel new MyModule TestInterface test kernel Get
  • 解析具有同名子节点的 XML 文件

    我有一个 XML 文件 下面是简要版本
  • 如何在双击时动态隐藏AppBar?

    我想在容器上的 DoubleTap 上动态隐藏和显示应用程序栏 并带有一些隐藏动画 但此链接中的解决方案不适用于我的项目 Flutter 如何在页面上动态显示或隐藏应用程序栏 https stackoverflow com question
  • 重构静态方法/静态字段以进行测试

    我有以下遗留代码 public class MyLegacyClass private static final String jndiName java comp env jdbc LegacyDataSource public stat
  • GWT 中会话超时的鼠标移动

    我正在研究 GWT 在我的应用程序中 我想在 2 分钟后未执行任何操作 包括鼠标事件 时添加会话超时 我编写了一个类 其中使用了 GWT 会话对象 public static boolean ValidSession HttpSession
  • 如何将用户凭据从控制台传递到 SharePoint Online?

    我正在尝试使用控制台可执行文件中的上下文令牌连接 SharePoint 2013 Online 网站 但是 它给了我错误The remote server returned an error 403 Forbidden 这是代码片段 str
  • 为什么使用 Xamarin 的 MobileServiceClient 单点触控实现的流量未显示在 Fidder/Charles 中

    这可能与以下问题相同 使用 MonoTouch HttpClient 和 Charles 代理时的 HTTP 流量监控问题 https stackoverflow com questions 23492126 http traffic mo
  • 如何让测试资源管理器适用于 Python VS Code?

    我最近安装了 VSCode 和它的 python 扩展 一切都很顺利 但测试资源管理器不会填充测试 我已经运行了测试发现 甚至可以运行测试 但资源管理器不会填充任何信息 在上面的截图中我们可以看到 空的测试资源管理器 我的 python v
  • 在node.js和socket.io中发送数组时的错误

    我使用socket io版本0 8 4 我将我的问题归结为以下几点 我的数据看起来像这样 data prop1 data prop1 push man data prop2 data prop2 hey man 我通过以下方式将数据从服务器
  • 为 Log4j2 配置 Grails 3

    我们想使用 Log4j2 作为与 grails 3 的日志绑定 从目前我能了解到的情况来看 我们有许多使用各种记录器的从属依赖项 因此我们需要使用 SLF4J API 然后 我们需要将每个 API 重新定向到 Log4j2 绑定 而不是让
  • Kinect 编程的要求

    我希望使用 Kinect ToF 摄像头进行编程 但我不确定这样做的硬件和软件要求 我读过很多涉及这个主题的文章 书籍 但似乎存在一些不一致之处 让我有些困惑 问题 我需要购买什么 Kinect 产品才能确保拥有在计算机上使用它进行软件开发
  • 使用带有 SSL 的 ODBC (5.1) 连接 MySQL

    我们有一个客户端应用程序 通过 ODBC 连接器 服务器是托管 专用网络服务器 连接到我们的在线 MySQL 数据库 5 1 44 community log 这效果非常好 但是我无法使用 SSL 让它工作 这是我到目前为止所做的 1 My
  • 如何创建纯解决方案级 NuGet 包

    我想创建并分发一个 NuGet 包 安装后仅将整个解决方案安装到根目录packages 文件夹 引用中的包 NuGet packages config file 我已经找到了一些有关该主题的 NuGet 包格式的信息 并且根据NuGet 常
  • 将 Gradle 模块包含到 Maven 项目中

    我们有一个使用 Maven 作为构建系统的大型项目 我们决定在未来的项目中将使用 Gradle 作为更方便的工具 但我们也希望将 Gradle 用于我们的遗留项目 我认为从 Maven 迁移到 Gradle 会非常痛苦 因为 POM 文件中
  • 如何从tinyMCE禁用HTML标签

    https www dropbox com s g2nry5ifx0x9v52 2013 12 20 2011 20 26 Ingage 20Admin 20Panel png https www dropbox com s g2nry5i
  • CoreData:仅获取最后一个元素,而不是全部(iPhone)

    Welcome 我使用 Core Data 来存储数据 我需要这样一个方法 它只返回实体的最后 7 个元素 我的问题是我应该如何修改这段代码 它获取所有元素 但我只需要最后 7 个 NSEntityDescription entity NS
  • 如何从 shell/bash 脚本中更改 Linux 上的桌面壁纸

    我想从 shell bash 脚本更改 Linux 上的壁纸 使用其完整路径更改为特定文件 我已经找到了几种方法 见下文 来做到这一点 但这些方法并不适用于所有桌面环境 a 使用 gnome settings daemon gsetting
  • 在react-router中调用getComponent时如何显示加载UI?

    我对 React 很陌生 我不知道如何在使用 getComponent 加载路由时呈现 正在加载 屏幕 getComponent 调用工作正常并显示组件 但 UI 上没有任何迹象表明请求和响应之间发生了任何情况 这就是我想弄清楚的 impo