How to open the modal of next screen while navigating in react native? - javascript

I wanted to open the modal of the another screen (lets say B) from my current screen(lets say A) by passing the props as { showModal: true }.
In my screen A, I have passed the props from A to B like:
Navigation.push(componentId,'B',null,{showModal: true});
In my screen B, I got props showModal and open the modal of screen B like:
useEffect(() => {
// some async API calls
},[]);
useEffect(() => {
if (showModal) {
setTimeout(() => modalRef.current?.setModal(true), 4000); // inside the async function call
}
}, []);
Here you can see i have shown the modal using the ref, but not state because there was other neighbour states which caused re-rendering issue and the modal was not opening. In this case, the modal opens up as i have delayed the opening of the modal since there are some other async API calls as well.
So my question is that is there other alternative solution than this?

I think setTimeout is the wrong approach because anyone does not know about time for APIs fetching so, You can open the model after all APIs successfully fetched.

You can use AppNavigator to go to the next screen.
import {NativeStackNavigationProp} from '#react-navigation/native-stack';
import {AppNavigator} from '#navigators';
const goToFinanceScreen = () => {
navigation.navigate('test');
};

Related

NextJs Link causes Error: Loading initial props cancelled

I have nextjs 13 app and I have navbar component with some Nextjs links. After pressing the link and the page starts loading if you click the same link fast some times it throws this error: Error: Loading initial props cancelled.
What I did:
//navbar.ts
const [loadingPath, setLoadingPath] = useState()
useEffect(() => {
Router.events.on('routeChangeComplete', () => setLoadingPath(undefined))
}, [])
const onClickExample= (e) => {
e.preventDefault()
setLoadingPath('/example')
if (loadingPath === '/example' || router.asPath === '/example') return
router.push('/example')
}
//jsx
<Link href="/example" onClick={onClickExample}>Go to Example</Link > // Nextjs Link
There are some discussians like this github issue. It happens on Nextjs 12 too according comments around the net.
This is common user behavior and it's weird to throws such errors.
How do you handle it? Any elegant solution?
I don't see any reason to use onClick in your <Link> here the property href="/example" will make you navigate to /example.
and if you are doing this just to prevent the error then what you are trying to do will not help :
setLoadingPath('/example')
if (loadingPath === '/example')
makes no sens, the loadingPath state will not be updated untill the next render.
This is happening when you try to navigate to another page while the current one is still loading, usually because of a slow connection there are some althernatives like :
const [navigation,setNavigation] = useState('')
//...
const onClickExample = (e) => {
e.preventDefault();
setNavigation("/example"); // when the user clicks you update 'navigation' to the wanted URL to trigger a render
};
//...
useEffect(() => {
if (navigation !== "") { // prevent navigation for the first render
setTimeout(() => {
router.push(navigation); // when the component finishes rendering useEffect runs because navigation is updated then navigate to the wanted URL
}, "500");
}
}, [navigation]);
But you cannot do this with <Link> because it requires href so it will navigate to the given path anyway.
<a onClick={onClickExample}>Go to Example</a>
Try to do it without setTimeout maybe it works for you. In my case it was happening only in development.

EXPO useEffect not called on navigating to same screen

I have one screen which called useEffect when rendered first time in the flow.
The second time I navigate to the screen in the flow , use Effect is not called but I want to call a function upon first time before , after or during render function is called when we navigate a second time to the same screen.
Here is the navigate call for everytime navigating to this screen from various screens
navigation.navigate("x", { u:type, s:title});
The following is the structure for my screen. I am not using components but functions with navigation
const x = ({ navigation}) => {
...
return (
<View style={styles.a}>
...
</View>
);
};
export default x;
The problem here is that a screen remains mounted in react-native after the initial navigation. Thus, a useEffect with an empty dependency array won't be called subsequently on navigation.
Notice that this behavior differs from the web.
If you are coming to react-navigation from a web background, you may assume that when user navigates from route A to route B, A will unmount (its componentWillUnmount is called) and A will mount again when user comes back to it. While these React lifecycle methods are still valid and are used in react-navigation, their usage differs from the web.
The recommended way to solve this is described here. For your case this can be solved as follows.
import { useFocusEffect } from '#react-navigation/native';
const x = ({ navigation}) => {
useFocusEffect(
React.useCallback(() => {
// called when screen is focused, thus everytime on navigation
return () => {
// unfocus... cleanup ... or whatever
};
}, [])
);
...
return (
<View style={styles.a}>
...
</View>
);
};
export default x;
useEffect will be called on first load of your functional component or when some dependency will be changed. Everything remains the same, so your useEffect will not work. Consider using useFocusEffect from react-navigation lib instead.

how do i update a navbar on an api call (specifically a google signin)

i'm having a tough time understanding the hook concept in this case:
the user signs in through google, updating the session state.
this updates a visitorType state from 'viewer' to 'buyside'...
and then my navbar is supposed to adjust. but it doesn't, unless switch from the browser to another app and then back again...
const { data: session } = useSession(); //next-auth login sessions
const [visitorType, setVisitorType] = useState('viewer')
const visitorRef = useRef(visitorType);
useEffect(()=>{
return(
() => {if (session) {
visitorRef.current='buyside';
setVisitorType('buyside')}
}
)
},[session])
from what i understand, useRef gets the value of something between re-rerenders? and useEffect is asynchronous, so it lags behind? - so, not sure how i can update a reference..
The function returned by useEffect fires when the components unmounts. I think what you want is:
useEffect(()=>{
if (session) {
visitorRef.current='buyside';
setVisitorType('buyside')}
}
},[session])
Regarding your question on useRef:
when you set visitorRef.current. No rerender is triggered.
when you call setVisitorType, a rerender happens

How to make a modal toggle only when navigating from a specific page in React Native?

I have two screens in my app called "ReadyScreen" and "RunningScreen."
The user can access ReadyScreen on one of two ways:
1: When they are getting ready to start a run (when they click the start run button)
2: When they finish the run, they will be navigated from RunningScreen back to the ReadyScreen.
When the user finishes a run, i want a modal to toggle showing them:
How Many Steps They Ran, Average HR, etc.
but I only want it to toggle when they are navigating from "RunningScreen."
Would this require an "if" statement basically stating if they navigated from RunningScreen the modal will toggle, else, it will not? Or is there more nuance to this?
i would send a route param in RunningScreen:
navigation.navigate('ReadyScreen', {
didComeFromRunningScreen: true
})
then in RunningScreen get the variable:
const RunningScreen = ({ route }) => {
const { didComeFromRunningScreen } = route.params
useEffect(() => {
if(didComeFromRunningScreen){
//show modal
}
}, [])
}
i believe this should work.

react-native navigation false route params in navigation listener

I am using react native navigation and have two tabs. One of them has a list of entites, the other has a form to submit entities. When ever a new entity is submitted, I'd like to refresh the first tab to be sure, the newest data gets loaded.
I navigate to the first tab like this:
navigation?.navigate('Main', {refresh: true});
This props gets saved as follows:
let {refresh} = route.params;
To check, if the screen needs to refresh, I added a listener in useEffect() like this:
useEffect(() => {
const unsubscribe = navigation.addListener('focus', () =>{
if(refresh){
doRefresh()
}
})
}, [])
Unfortunately, neither "refresh" nor "route.params" directly is ever true inside the listener. Passing the param works, because I took a closer look at the var and it gets true, whenever I submit.
Do I need to access the route.params inside a navigation listener in another way?
Thanks and hit me up, if you need more information on this
The issue is that your useEffect only runs once as your dependencies array [] is empty, and therefore your listener only receives the initial value of refresh.
You need to pass refresh as a dependency to useEffect, and I don't think you even need the focus listener in your case so you would end up with this:
useEffect(() => {
if (refresh) {
doRefresh()
}
}, [refresh])
const onPressCountry = (item,index) => {
navigation.push('SignUp2', {selectedCountryId:item?.countryID, selectedCountryName: item?.name} )
}
use navigation.push instead of navigation.navigate

Categories