0

I am trying to make a timeout page when loading certain data from the backend takes too long, but i am failing at something very easy (i think), my code currently

const Layout = ({ lang: { language, loadingLang }, getLang }) => {
  const time = useRef(0);
  const timer = useRef(false);
  useEffect(() => {
    // Get the language
    if (!language && !loadingLang) {
      getLang();
      //Start the timer
      timer.current = setInterval(function() {
        ++time.current;
        console.log(time.current);
      }, 1000);
      return () => {
        clearInterval(timer.current);
      };
    }

    // Prevent any useless errors with net line:
    // eslint-disable-next-line
  }, []);

  if (language && !loadingLang) {
    // stop the timer if whe have the data
    clearInterval(timer.current);
  }

  if (!language && time.current > 10) {
    return <LoadingTimeoutPage />;
  }

  // If the language data does not exist or is loading show the preloader
  if (!language && time.current < 10) {
    return <Preloader />;
  }

  return (
    <Router>
      <NavBar />
      <Switch>
        <Route exact path="/" component={Home} />
        <Route exact path="/hire" component={Hire} />
        <Route exact path="/swimschool" component={SwimSchool} />
        <Route exact path="/login" component={Login} />
        <PrivateRoute path="/dashboard" component={DashBoard} roles={['any']} />
        <Route exact path="*" component={PDNE} />
      </Switch>
    </Router>
  );
};

It should be very simple i think but i just can't get it to work how it is supposed to, right now it will just show the preloader even after the 10 seconds have passed, am i doing something wrong that i am just overlooking?

6
  • You should show what function is consuming time. Is it getLang()? Does it return promise? Commented Mar 3, 2020 at 16:15
  • I don't think so, its a redux function. But yes getLang is consuming time thats why i start a timer when i run getLang Commented Mar 3, 2020 at 16:22
  • You are starting a timer but you never actually trigger a re-render when the timer value exceeds the limit. A changing ref does not tigger a re-render. Commented Mar 3, 2020 at 16:22
  • How come a function like getLang is time consuming?! Commented Mar 3, 2020 at 16:26
  • Ah that would explain it, what is a better way to do this then? Commented Mar 3, 2020 at 16:26

1 Answer 1

1

You need to periodically check the timer value and trigger a re-render when it exceeded the limit:

const Layout = ({/* ... */}) => {
  const [limitExceeded, setLimitExceeded] = useState(false);
  const time = useRef(0);
  const timer = useRef(false);

  useEffect(() => {
    if (!language && !loadingLang) {
      getLang();

      timer.current = setInterval(function() {
        if(time.current > 10) {
          // trigger a re-render by setting limitExceeded to true
          setLimitExceeded(true);
          clearInterval(timer.current);
        } else {
          ++time.current;
        }
      }, 1000);

      return () => clearInterval(timer.current);
    }
  }, []);

  useEffect(() => {
    if (language && !loadingLang) clearInterval(timer.current);
  }, [language, loadingLang]);

  // ...

  if (!language && limitExceeded) {
    return <LoadingTimeoutPage />;
  }

  // ...
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.