Prevent going back to previous screen with React Native - reactjs

I'm working on an app with React Native and React Navigation. For most of the app, I have a bottom tab navigator and header. However, in one section of the app, the user can make a call and is taken to a screen with no navigation. The user shouldn't be able to navigate to the previous screen without ending the call. How can I prevent the user from going back?

if you use react-native-navigation v5, it supports several listeners and the one you need is beforeRemove this is being called before the screen gets removed and you can prevent it's default behaviour conditionally.
useEffect(() => {
navigation.addListener("beforeRemove", (e) => {
if(yourCondition) {
return ;
} else {
e.preventDefault();
}
});
}, [navigation]);

Related

Preventing goBack with useNavigate hook

Is there a way to prevent back navigation using react's useNavigate hook? I'm currently using navigate("/",{replace: true}) for the time being but would like to have a proper solution for it.
The only way to fight browser's own mechanism like History and navigation is to check history.length:
useEffect(() => {
if (global.history.length> 1) {
window.open(window.location.href, "_blank");
}
}, []);
Imo it's rather confusing. Also when user opens new tab, history.length becomes 1. So code above will not bring another tab only if opened from bookmark/by clicking link with target="_blank".

which function is called when screen is returned from other screen in react native?

I can see the React native component life cycle. componentDidMount, UNSAFE_componentWillMount, etc
I thought UNSAFE_componentWillMount is called when screen is resumed. But it is not called.
I use React 17 over, React Native 0.68.1, and I use navigation.goBack() to return from second screen to first screen.
Which function is called when screen is resumed? Or what other way to do that?
You need to be careful here. In react-native a screen remains mounted on navigation. This 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.
Hence, if you navigate via goBack, the componentWillMount will not be called again, since the screen remains mounted. There is a general workaround for this problem which is documented here in the React Navigation lifecycle events section.
For functional components, we can use the useFocusEffect hook as follows.
useFocusEffect(
React.useCallback(() => {
// Do something when the screen is focused
return () => {
// Do something when the screen is unfocused
// Useful for cleanup functions
};
}, [])
);
For class components, we can use a focus listener. This is documented here.
class SomeClassComponent extends React.Component {
componentDidMount() {
this._unsubscribe = navigation.addListener('focus', () => {
// do whatever
});
}
componentWillUnmount() {
this._unsubscribe();
}
...
In some cases it might be more convenient to still use functional components. We can simply wrap a legacy class component into a functional component as follows.
const Wrapper = () => {
// useFocusEffect from above.
return <SomeClassComponent />
}
In react native when you change screen and come back to the previous screen it doesn't rerenders so using useEffect hook doesen't work. However you can use useFocusEffect hook provided by the react navigation. You can read more in details Here

React Navigation: addListener('didFocus') called over and over

I'm using react-navigation#4.0.10 in my React Native app, and I want to trigger a function whenever the user switches tabs in my tab navigator. I tried this:
componentDidMount() {
this.props.navigation.addListener('didFocus', () => {
<call function>
})
}
The problem is this now gets called rapidly over and over, and never stops.
Is there a better way to approach this problem?

How to detect swipe back event in iphone React Native

I am developing a react native app, I am trying to clear setinterval function by backhandler event. It works correctly on android phone, but there is no back button in iphone, so I can't stop setinteval function. How can I detect swipe back handler?
Assuming that you are using #react-navigation/native. You can add Listener for beforeRemove event. This event is emitted every time the component is removed/user tries to leave the screen.
navigation.addListener('beforeRemove', (e) => {
e.preventDefault()
//clear setInterval here and go back
})
You can find more information here
For me, this snippet is working fine. you can place this code in useEffect or componentDidMount. Make sure to cancel this event if you are navigation between the screens.
For reference, you can visit https://reactnavigation.org/docs/5.x/navigation-events
and select the react-navigation version according to your project.
const gestureEndListener = () => {
console.log(" Called when screen is unmounted " )
}
useEffect(() => {
const gestureHandler = navigation.addListener('didBlur', gestureEndListener);
return () => {
gestureHandler.remove();
};
}, []);

React Native: Screen not re rendering or triggering useEffect() while using react navigation

I need to refresh the screen, when the navigation come from a specific page. But when the page navigates, useEffect method or any other method is not getting triggered. I understand that, the method is not getting triggered as the state or props has not changed. But is there a way to trigger it, please let me know. Also I tried didFocus, but it refreshes every time the screen comes into focus, but I want refresh to be done only when it comes from particular screen.
I haven't used useEffect yet but i did this with react-navigation to activate a change in props.
On the screen you want to refresh when it gets to it add the didFocus listener:
this.props.navigation.addListener(
'didFocus',
payload => {
console.debug('didFocus', payload);
if (this.props.navigation.getParam('shouldRefresh')) {
this.props.navigation.setParams({ shouldRefresh: false });
// Do something
}
}
);
When you navigate to that screen and want it to refresh:
this.props.navigation.navigate('SomeScreen', { shouldRefresh: true });
Hope it helps.

Resources