React-native componentWillMount not calling - react-native

I am new in react-native I have two screens in my stack. Login and Home.
I want to go back to login from a button on home.
I am writing this code
this.props.navigation.navigate('loginScreen')
but in login screen componentWillMount method is not calling. I want to reset my form when user come on login screen from home.
Can anyone help me here?
Thanks in advance.

The this.props.navigation.navigate('loginScreen') don't work because you are now in loginScreen.
If you want to restart page this code isn't good. because have a loop!
correct code:
just when navigate to loginScreen from home use:
this.props.navigation.push('loginScreen')
NOT IN "componentWillMount"

To go back from login from home , you should use this.props.navigation.goBack() if the screen is immidiately before home.
Secondly, you should not use componentWillMount since it is deprecated and will be removed from React 17 onwards. Instead use componentDidMount
Since the component is already mounted therefore it won't call the react lifecycle events componentDidMount again. Therefore you should use the react-navigation listeners didFocus event.
didFocus: the screen focused (if there was a transition, the transition completed)
componentDidMount () {
this._onFocusListener = this.props.navigation.addListener('didFocus', (payload) => {
// Perform the reset action here
});
}

Since your Home and Login Screens are both under the same StackNavigator, when you go from Home back to Login the state stays the same as the component doesn't unmount. The recommended way to solve this is using the SwitchNavigator of react-navigation. Read this very helpful part of the documentation below
https://reactnavigation.org/docs/en/auth-flow.html
You may not be familiar with SwitchNavigator yet. The purpose of
SwitchNavigator is to only ever show one screen at a time. By default,
it does not handle back actions and it resets routes to their default
state when you switch away.

The perfect solution is with this.props.navigation.push('Login'), I tried with SwitchNavigator but it doesn't provide navigationOptions for header.

Related

Why does my state persist on screen change?

I am developing a React Native app and I am currently using a component in 2 different places of my app. I navigate from one place to another using a Drawer Navigator (React Navigation v6). This component updates a state when receiving a response from an API. However, if I switch to the other place where this component gets rendered, the state remains (therefore the visual message from the API appears inside it).
Why does this happen? Shouldn't all states reset on unmount and get the initial value (the one passed to useState()) when the component gets mounted again? This not the behavior I want and from what I know, this was not supposed to happen.
What can I do to make my state not persist on screen change? I have implemented the code below to be executed when a menu screen is selected, but has no effect on this issue:
navigation.dispatch(
CommonActions.reset({
index: 0,
key: null,
routes: [{ name: targetScreen }]
})
This behavior in react-native differs from react. This is documented here.
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.
Consider a screen A and a screen B. Suppose we navigate from A to B.
When going back from B to A, componentWillUnmount of B is called, but componentDidMount of A is not because A remained mounted the whole time.
This is valid for all navigators in react-native-navigation. Thus, if we have a tab bar navigation with 5 tabs, and each tab nests a Stack, then we could navigate on one stack to a certain depth, then switch the tab, and then switch the tab back again, and all screens visited will remain mounted.
Edit: In response to the comments. The recommended standard pattern to resolve your issue is as follows.
// some state in my component
const [state, setState] = useState()
useFocusEffect(
React.useCallback(() => {
// set state to initial value
setState()
}, [])
);
This is described here.
Your component does not unmount when you navigate out of component. Consider manually reseting your state inside this hook useFocusEffect

React Native component is not triggering componentDidMount() after first mount

I have two react native components, One is profile(showing logged user details) and another one for login.
In login component I set the user details to AsyncStorage.
import {AsyncStorage} from 'react-native';
Adding user to AsyncStorage:
const user = {
fname:"Tenusha",
lname:"Guruge"
}
AsyncStorage.setItem("user",JSON.stringify(user))
In the profile component I read the AsyncStorage
componentDidMount() {
AsyncStorage.getItem("user").then(user => {
console.log(user)
this.setState({user})
})
}
When logout I clear the AsyncStorage:
AsyncStorage.removeItem("user")
Problem is Once I log in and set the user details to AsyncStorage, it store the data and I can view them in profile component. Once user logout, the data in storage are cleared, but when I navigate to profile component the previously loaded data is still there.
I need a way to read the current AsyncStorage data when every time user navigate to profile component.
To be sure a component is unmounted you can use createSwitchNavigator.
You can use a loginScreen as child while the other child is your Drawer.
When doing a logout you clear your asyncStorage and then navigate to the loginScreen and the SwitchNavigator will unmount your Drawer.
DrawerNavigation will keep the screens active while moving between his childs after every screens's first focus, making every componentDidMount getting triggered only at first render.
Track navigation changes and clear state here
Consider state-manager like redux it will be cleanest approach
Your issue is that your state is not getting cleared when using DrawerNavigator instead you can use stackNavigator if you want your component to unmount when navigating out and clearing the state automatically.
Another approach can be of using state management library such as redux or flux and clear out state whenever user is logging out.

How to redirect to notification page when app is opened after clicking FCM notification?

I have implemented firebase cloud messaging in my app successfully. But when a new notification appears, my app should open and then redirect to the notifications page from app.js.
The app is showing log info when the notification is clicked but when I try this.props.navigator.push("Notification"); in that function, it shows an error undefined is not an object(evaluating this.props.navigation.push)
I am guessing this is because I haven't yet initialised my stacknavigator but I don't know this for sure. I am using react-navigation in my app.
Here is the function in my app.js that gets called when the notification is clicked.
const notificationOpen = await firebase.notifications().getInitialNotification();
if (notificationOpen) {
const { title, body } = notificationOpen.notification;
console.log('getInitialNotification:');
this.props.navigator.push("Notification");
}
Also, the navigation code is not working even in my render function in app.js so I think props is not initialised in app.js.
Can anyone help me fix this and land me to the notification page?
Considering you have a route called Notification in your stack navigator and also your app.js has access to the navigator's navigation prop, then you might want to use this.props.navigation.navigate('Notification') in case you are using react-navigation.
The problem with your code is this.props.navigation doesn't have any method called push so it will surely give an undefined error. To know more about navigation prop consider going through this doc.

App Navigation state persisting EVEN IF app closed and restarted

I have a react-native app with two screens, Home and Details. Using react-navigation, Ive set the Stack navigator as following
const RootStack = createStackNavigator(
{
Home: FormComponent,
Details: DetailScreen
},
{
initialRouteName: "Home",
headerMode: "none"
}
);
Home contains a form, which once submitted, navigates to the Details screen with relevant data (using navigation.navigate("Details",{some data})). At this point, if I exit the app, and then open it again, the Details screen loads, with all the data preserved(Instead of the Home screen). I logged the navigation object data (this.props.navigation.) and it prints like the app was never closed.
Am I missing something here? Im new to React Native and Navigation, but from what I understand this is not expected behaviour.
Tried uninstalling app and rebuilding. This resets the app and Home screen loads. If I try reinstalling without uninstalling, back to same behaviour.
Tried also manually forcing navigation.goBack() on ComponentWillUnmount() but no difference.
This should've been a comment but sadly i don't have enough reputation.
Could you check if you haven't accidentally set a persistenceKey as a navigator prop?
https://reactnavigation.org/docs/en/state-persistence.html

React Native - AppState 'change' event get no call when navigating between screens

AppState.addEventListener('change', ...)
The listener does not getting any call. I'm using StackNavigator to put root screen and the screen with AppState
(Updated) It's been called when I restart the app. But the Component where I use AppState is not yet the active screen
In my case, I just want to get notified when a navigation come back to or leave a screen. So I can simply do this
this.props.navigation.addListener('didFocus', ...);
this.props.navigation.addListener('didBlur', ...);
The problem with AppState still remains