0

I want to show a Loader on top of everything while fetching data from my API. I asked this question and implemented the answer, and it is working, but it shows it not on top level, but inside the page itself. When looking at the html tree I can see that it is on the top level.

This is what happens when btnAll is clicked:

enter image description here

After scrolling down:

enter image description here

This is the HTML tree:

enter image description here

Why does it put it inside the page?

loading.provider.js

import { createContext, useContext, useState } from "react";

const LoadingContext = createContext({
  loading: false,
  setLoading: null
});

export function LoadingProvider({ children }) {
  const [loading, setLoading] = useState(false);
  const value = { loading, setLoading };
  console.log(`LoadingProvider: ${loading}`);
  return (
    <LoadingContext.Provider value={value}>{children}</LoadingContext.Provider>
  );
};

export function useLoading() {
  const context = useContext(LoadingContext);
  console.log(`Using LoadingContextProvider`);
  if (!context) {
    throw new Error('useLoading must be used within LoadingProvider');
  }

  return context;
};

app.js

export default function App({ Component, pageProps }) {

  return (
    <>
      <CssBaseline />
      <AppStateProvider>
        <LoadingProvider>
          <Loader />
          <Layout>
            <Component {...pageProps} />
          </Layout>
        </LoadingProvider>
      </AppStateProvider>
    </>
  );
};

Loader.js

import { useLoading } from "@/Providers/loading.provider";
import { useEffect } from "react";
import LoadingScreen from "./LoadingScreen";

const Loader = () => {
  const { loading } = useLoading();

  useEffect(() => {
    console.log(`[app.js/#useEffect]: useLoading() value changed to: ${loading}`);
  }, [loading]);

  return loading && <LoadingScreen loading={true} bgColor='#fff' spinnerColor={'#00A1FF'} textColor='#676767'></LoadingScreen>;        
};

export default Loader;

LoadingScreen.js

import styles from './LoadingScreen.module.css';

export default function LoadingScreen() {

  return (
    <div className={styles.loading}>
      <div className={styles.dot}></div>
      <div className={styles.dot}></div>
      <div className={styles.dot}></div>
      <div className={styles.dot}></div>
      <div className={styles.dot}></div>
    </div>
  );
}

This is the css part of style.loading inside LoadingScreen.module.css:

.loading {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 99;
  background-color: #FFFFFF;
}

I am calling it inside [identifier].js page like that:

import { useLoading } from "@/Providers/loading.provider";

export default function MainPage({ response }) {
  const { loading, setLoading } = useLoading();
  const btnClickedAll = async (data) => {
    setLoading(true);
  };

  return (
    <Fragment>
      <Button sx={{ ml: 2 }} key={'btnAll'} onClick={btnClickedAll} variant="contained">All</Button>,
    </Fragment>
  );
}
ytpm
  • 4,962
  • 6
  • 56
  • 113

1 Answers1

0

Updated:

Try set the style .loading position: fixed;


Old:

Try moving down the <Loader /> in app.js

...
        <LoadingProvider>
          <Layout>
            <Component {...pageProps} />
          </Layout>
          <Loader />
        </LoadingProvider>
...

Or it's better to put Loader in loading.provider.js and remove <Loader /> from app.js

...
    <LoadingContext.Provider value={value}>
      {children}
      <Loader />
    </LoadingContext.Provider>
...
Raul Li
  • 1
  • 1
  • Still the same problem.. – ytpm Feb 14 '23 at 12:05
  • Ahhh, just checked your question again, and realized you met the problem when you scroll down the page. updated my answer. – Raul Li Feb 17 '23 at 09:56
  • Thank you, but now it's above the whole page except the `Top Navigation Bar` and `Sidebar`. How do I make it on top of everything? – ytpm Feb 19 '23 at 09:24
  • @ytpm to make an element on top of everything, we usually put the element as the last child of the body tag. – Raul Li Mar 19 '23 at 12:07