8

I'm coming from AngularJS world and start some days ago writing my first React App with react-router, in AngularJS I do:

app.directive('Loading', function($rootScope, $timeout) {
    return {
        restrict: 'E',
        replace: true,
        template: '<p>Loading</p>'
        link: function(scope, element) {
            $rootScope.$on('$routeChangeStart', function(event, currentRoute, previousRoute) {
                element.removeClass('ng-hide');
            });

            $rootScope.$on('$routeChangeSuccess', function() {
                element.addClass('ng-hide');
            });
        }
    };
});

and then I just add <Loading></Loading>. So now in my React App I have:

class App extends Component {
  render() {
    return (
       <Router>
        <div>
          <ul>
            <li><Link to="/">Home</Link></li>
            <li><Link to="/about">About</Link></li>
          </ul>

          <hr/>

          <Route exact path="/" component={Home}/>
          <Route path="/about" component={About}/>

        </div>
      </Router>


    );
  }
}

and my two components are simple:

class Home extends Component {
    render() {
        return (
            <h1>Home</h1>
        );
    }
}
class About extends Component {
    render() {
        return (
            <h1>About</h1>
        );
    }
}

Can I do this without using reduxJS?

Yannick Loriot
  • 7,107
  • 2
  • 33
  • 56
John
  • 483
  • 3
  • 9
  • 18

3 Answers3

6

you can use a High Order Component in react to do this in a generic way.

Look is a example:

https://github.com/thejameskyle/react-loadable

Gerardo Perrucci
  • 704
  • 7
  • 13
2

If you fetching some data I made a small package react-router-loading that allows you to show loading indicator and load some data before switching the screen.

Just use Switch and Route from this package instead of react-router-dom:

import { Switch, Route } from "react-router-loading";

Add loading props to the Route where you want to wait something:

<Route path="/about" component={About} loading/>

And then somewhere at the end of fetch logic in About component add loadingContext.done();:

import { LoadingContext } from "react-router-loading";
const loadingContext = useContext(LoadingContext);

const loading = async () => {
    //loading some data

    //call method to indicate that loading is done and we are ready to switch
    loadingContext.done();
};
Victor Trusov
  • 1,057
  • 9
  • 19
  • I had a look on the package and I would love to use it for my project. One question, is it possible to change the position of the topbar? Right now it is on top level of screen, but I want to have it at the bottom of my header component. I am not sure if this can be achieved with ```topbar.config({})```. Could you please tell me what can I do? – user12051965 May 02 '21 at 13:33
  • 1
    @user12051965 I'm using topbar (http://buunguyen.github.io/topbar/) in my package, but it looks like where is no option to achieve it through config. Instead you can do it with css. Just add something like `.topbar { top: unset !important; bottom: -12px;}` to your css and adjust bottom value if necessary. – Victor Trusov May 02 '21 at 17:13
0

I think by using useLayoutEffect, you can put a loader on every route change. I anyone have a question feel free to ping me.

import { useLayoutEffect, useState } from "react";
import RoutesWrapper from "./components/RoutesWrapper";
import Loader from "./components/Loader";
import { useLocation } from "react-router-dom";
function App() {
  const [loading, setLoading] = useState(true);
  const { pathname } = useLocation();
  useLayoutEffect(() => {
    setLoading(true);
    const timer = setTimeout(() => {
      setLoading(false);
    }, 2500);
    return () => clearTimeout(timer);
  }, [pathname]);
  return loading ? <Spinner /> : <RoutesWrapper />;
}

export default App;
Moritz Ringler
  • 9,772
  • 9
  • 21
  • 34
idembele70
  • 81
  • 4