I am using iframe in react component.I want to check if the url has responded 200 and loaded completely and want to handle error and loading scenarios. I tried to access the iframe id but it's throwing corss origin frame error. Please suggest
If you want add a loading before iframe loaded completely you can handle it by checking when docuemnt of iframe loaded document.getElementById('myframe').contentWindow.document
you can create a function in your react component and check iframe like this:
const [ loading, setLoading ] = useState(true);
const checkIframe = () => {
const iframeDocument = document.getElementById('myframe').contentWindow.document;
if(iframeDocument){
setLoading(false);
} else{
setTimeout(() => {
checkIframe();
}, 1000);
}
}
Related
I am fetching data from a backend api.
const Home = () => {
const [posts,setPosts]=useState([]);
useEffect(()=>{
const fetchPosts= async ()=>{
const res = await axios.get("/posts")
setPosts(res.data);
}
fetchPosts();
},[])
console.log(posts)
However in doing this, the initial state of posts which is [] is also getting printed.
Why is this happening and how can I avoid this and only get the data?
that is the reason why you see loading in real-world App because communication between server and client takes time so we show loading or show error if API gets error the same logic goes to component or element whatever your are trying to show as well
if(posts.length > 0) {
console.log(posts)
} else {
console.log("Loading...")
}
Image of Code
So I had a question about how to run rendering in react native after data is loaded from a database. In my code, I want to list prescriptions, but it keeps giving errors as it tries to load the prescription in the rendering function before executing the code that reaches out to firebase and gets the prescription data. How do I make it so that the rendering happens after the firebase data is gathered.
The easiest way to do this is to just have a loading state in React, this can default to true and once the data has been retrieved from Firebase you set to false. Then in your jsx you can return a loader or similar while the loading state is true and only render the rest of the screen that relies on the Firebase data once it's available and loading is set to false. Here's a minimal demo of this concept:
https://codesandbox.io/s/great-shockley-i6khsm?file=/src/App.js
import { ActivityIndicator, Text } from "react-native";
const App = () => {
const [loading, setLoading] = useState(true);
useEffect(() => {
// This is where you would have your Firebase function.
setTimeout(() => setLoading(false), 5000);
}, []);
if (loading) {
return <ActivityIndicator />;
}
return <Text>This is my app showing Firebase data</Text>;
};
export default App;
If you want to read a bit further and handle a potential error state if the Firebase function fails then here's a neat article to avoid an anti-pattern having a loading, success and error state. https://dev.to/tehaisperlis/the-loading-anti-pattern-7jj
If you look at the documentation here (https://rnfirebase.io/firestore/usage)
this is there get() example
import firestore from '#react-native-firebase/firestore';
const users = await firestore().collection('Users').get();
const user = await firestore().collection('Users').doc('ABC').get();
This means that you have to get() this data through async/await so do this below
useEffect(()=>{
const fetch = async ()=>{
/*
Your get code here
*/
const users = await firestore().collection('Users').get();
}
// Call fetch
fetch();
},[])
I am trying to deepLinking and catching the url when url open the page on the screen which is functionally works when my app is not working on the background. However, it doesn't work if app is working on the background.
const isFocused = useIsFocused();
useEffect(() => {
getCode();
}, [isFocused]);
const getCode = async () => {
//we will generate a button in the forget password email, link will include a url ===> mobile://auth/new-password?verification=534396
const url = await Linking.getInitialURL();
console.log('url', url);
if (url?.includes('new-password')) {
//problem, it may not work if app is still working on the background
const query = queryString.parseUrl(url);
const verifyCode = query.query.verification;
setVerificationCode(String(verifyCode));
setIsLoading(false);
} else {
Alert.alert('Something went wrong');
}
};
When I directlinked to application with the link, it console log as "url null". Is my problem on the focusing part or on the getInitialUrl function?
I was experiencing a similar issue.
In my case we used linking from NavigationContainer and it would open the same X screen left on background regardless if the deeplink data had a different value for that screen.
I fixed it by using the getId on Stack.Screen:
const getId = ({ params }) => params?.id;
<Stack.Screen name="X" component={XComponent} getId={getId} />
You can find more info on getId here https://reactnavigation.org/docs/screen/#getid.
I have multiple getServerSideProps in my project and I have a header which displays pages and I have to wait for a page to be opened once I click upon it since I need data to be fetched. Once they are fetched the page will be open.
One approach I used to show user a loading state is to use routeChangeStart BUT I stumbled upon one problem and so I would like not to use this case.
If I go on a page and the data is fetching I want to show user a spinner or some indicator and once the data is fetched I want to stop the indicator/spinner.
As you probably figured out, getServerSideProps runs on the server and is blocking. The fetch request needs to complete before the HTML is sent to the user (i.e., the page is changed). So if you want to show a loading indicator, you need to move that fetch request to the client.
For instance, if you probably have a page with this basic structure:
export default function Page({ data }) {
return <div>{data.name}</div>
}
export async function getServerSideProps() {
const response = await fetch('https://example.com/api')
const data = await response.json()
return {
props: { data },
}
}
const fetcher = url => fetch(url).then(res => res.json());
export default function Page() {
const { data } = useSWR('https://example.com/api', fetcher)
if (!data) return <LoadingSpinner />
return <div>{data.name}</div>
}
Or if you don't need SWR and can use a simple fetch request:
export default function Page() {
const [data, setData] = useState()
useEffect(() => {
fetch('https://example.com/api')
.then(async(response) => {
const json = await response.json()
setData(json)
})
})
if (!data) return <LoadingSpinner />
return <div>{data.name}</div>
}
P.S. If the initial fetch request in getServerSideProps used sensitive information (e.g., API secret credentials), then go ahead and setup a Next.js API route to handle the sensitive part and then fetch the new route.
I just used routeChangeStart.
I didn't want to use it since router.push('/map') didn't work in pages/index.tsx file but I solved this issue by creating a new component putting router.push in useeffect and rendering a loader.
routeChangeStart was in _app.js and because of this in index.js router.push() didn't work - I tested it
routeChangeStart - how it works?
When we click on a page the data is being fetched on the server and the page will only be displayed to us once the data is fetched. So we can make the next thing, we can just intercept the route change.
When we click on a link(we wait for data to fetch) we set loading state in routeChangeStart to true and if we moved to another page(it means we fetched the data) we invoke routeChangeComplete which runs once we moved to the route we wanted to, and here we set loading state to false. And after this I just pass the loading state using React Context
I have a NextJS website and I want to add a Splash Screen for before website is loaded
but because the Splash Screen is also in the NextJS code, it will loading when nextjs rendered on the server and the JS downloaded and executed on the client. in fact, it's useless because it will execute after the page is ready!
how can I do the Splash Screen before react completely loaded and executed ?
I also use nginx for proxy_pass
use this code
useEffect(() => {
const handleStart = () => { setPageLoading(true); };
const handleComplete = () => {
setPageLoading(false);
};
router.events.on('routeChangeStart', handleStart);
router.events.on('routeChangeComplete', handleComplete);
router.events.on('routeChangeError', handleComplete);
}, [router]);
and use pageLoding for show splash
For loading screen:
import React from 'react'
import useSWR from 'swr'
const fetcher = (url) => fetch(url).then((res) => res.json());
// your main function
export default function Profile() {
//for relative and absolute paths
const { data, error } = useSWR('/api/user', fetcher)
if (error) return <div>failed to load</div>
//for the loading you can create your custom component and insert instead of div, like this you keep same styling
if (!data) return <div>loading...</div>
if (data) return <div>hello {data.name}!</div>
}
Don't use useEffect hook, use this lib, better code and functionnality.
You have multiple possibility
You can start your Next Application on a page that contain a simple shimmer(splash screen), then replace the URL by url that contain SSR, and finally remove loading page for indexing with robot.txt. You can read more about this tips there.
You can insert inside on ... tag a CSS to show a loader(your splash screen). Then when the SSR function will be in loading the loader will be hide but when the browser download index.html(first file loaded, that contain style tag) the loader will be show before the browser download another assets(images, js, etc) and load it. You can read more about this tips there
The first tips will show loader fast than the second tip but require more steep(create another page, replace url, remove loader page for indexing)
You can do it by using DOMContentLoaded event, here an example:
In your _app.tsx and outside your function:
if (typeof window !== "undefined") {
document.addEventListener("DOMContentLoaded", () => {
// your code here ..
}
}