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:
After scrolling down:
This is the HTML tree:
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>
);
}