I'm really new to React, and I can't figure out how to display the "loading ..." screen when a route is loaded using getComponent. The getComponent call works fine and displays the component, but there is no indication in the user interface that anything is happening between the request and the response. This is what I am trying to understand.
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;
After trying to unsuccessfully force the βdownloadβ component to be displayed using onEnter or inside the getComponent function, I thought maybe I should try using Redux to set the load state to true / false and get my main view component to display the loading screen:
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);
This seems to work if I manually set the boot status using the action I wanted to do. But (and I feel that this will be the real question about the noob). I cannot figure out how to access the repository / dispatcher from inside the router.
I'm not sure if I'm using the wrong search terms or anything else, but I have absolutely no ideas, and every response-router / pruning tutorial seems to miss what I feel should be a common problem.
Can someone point me in the right direction (and also let me know if what I'm doing is really the best practice?)?
EDIT . I will try to clarify this a bit more. In the first block of code, you can see that if I click on the <Link to="/about"> element, then the getComponent function will work, which will lazy load the About.jsx component. The problem I am experiencing is that I cannot figure out how to show any loading indicator / counter that will appear immediately after clicking the link, and then replace it after the component is loaded.
MORE EDITING . I tried to create a wrapper component to load asynchronous routes, and it seems to work, however it feels really hacked, and I'm sure this is the wrong way to go about it. The route code now looks like this:
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;
The AsyncRoute.jsx page looks like this:
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;
If anyone has a better idea, please let me know.