Reputation: 7898
Scenario:
I have a Login.js
that I show as a Modal
from multiple screens wherever I have placed the check to see if a user is logged in or not. After the user successfully login I change a key called LoggedIn
to 1
from 0
using AsyncStorage
. Now when a user successfully logged in and the Modal
closes I want to rerender the scree user is on.
As I have a background in iOS, so there we have viewDidAppear
that runs every time there is a Modal
or user opens another app and comes back to the screen, etc.
So, what would be the equivalent of that in React Native? When a Modal close it should check if the LoggedIn
value is changed in AsyncStorage
and I've already prepared the components to render accordingly to the value of LoggedIn
value.
Code:
I have a screen Profile.js
in which I'm checking:
AsyncStorage.getItem("LoggedIn").then((value) => {
if (value === "1") {
setNeedLogin(true)
} else {
setNeedLogin(false)
}
});
const [needLogin, setNeedLogin] = useState(false);
Based on the above state I'm rendering the view as:
{
!needLogin &&
<View>
<Text>{userName}</Text>
<Text>{userEmail}</Text>
<TouchableOpacity>
<Text>Logout</Text>
</TouchableOpacity>
</View>
}
{
needLogin &&
<View>
<Text>You are not logged in</Text>
<Text>Please login or create a new account to see more information.</Text>
<TouchableOpacity onPress={() => {
alert('I am showing login screen here which is a modal')
}}>
<Text>Login or Sign Up</Text>
</TouchableOpacity>
</View>
}
Now when the Login.js
renders the Modal
and use logs in upon successful login I change the value of LoggedIn
to 1
and close the modal which shows the Profile.js
screen but when it shows it the view doesn't rerender. So, how would I check and change the state every time the profile.js
view appears?
Upvotes: 2
Views: 864
Reputation: 3187
First of all, you have to be clear in the mounting and updating process in react-native.
A componennt will re-redner whenever.
Now coming to your problem, your login component will not re-render until the above two conditions fulfilled, and as you are using AsyncStorage
it is not reactive
too.
So either you have to use some reactive storage like redux-persist
or you have to use focus listeners, I am assuming that you are using react-navigation so this focus listener might be a good fit for you.
Whenever the focus will be changed this function will be a trigger so you don't need to take care of updating the component etc.
import * as React from 'react';
import { View } from 'react-native';
function ProfileScreen({ navigation }) {
React.useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
// The screen is focused
// Call any action
});
// Return the function to unsubscribe from the event so it gets removed on unmount
return unsubscribe;
}, [navigation]);
return <View />;
}
https://reactnavigation.org/docs/function-after-focusing-screen/
Note: this focus listener will not work with react-native provided modal then you have to use react-navigation modal
If you don't want to use any focus listener or redux-persist you can simply check while opening the modal.
useEffect(()=>{
if(modalState){
AsyncStorage.getItem("LoggedIn").then((value) => {
if (value === "1") {
setNeedLogin(true)
} else {
setNeedLogin(false)
}
});
}
}, [modalState])
Upvotes: 0
Reputation: 2177
An equivalent of viewDidAppear
in react native would be componentDidUpdate
.
Sounds like you are dealing with 2 different components in the app, a Login
and a Modal
component.
One way to go about that would be passing a callback method to the Modal
component if you extend the reusability of the Modal
component.
For example,
class Login extends React.Component {
onLoginDone = props => {
// do some other things, like authenticate with the props data
}
render() {
<View>
<Modal onClose={this.onLoginDone} />
</View>
}
}
class Modal extends React.Component {
constructor(props) {
this.state = {
isVisible: false
}
}
onClose = () => {
this.setState({ isVisible: !this.state.isVisible })
this.props.onClose()
}
render() {this.state.isVisible && <View />}
}
Upvotes: 1
Reputation: 1
Once the user has logged in (when you have validated the login credentials), you can change the state variable needLogin to false, this will re-render the screen, provided the state is connected to the screen that you want to re-render
Upvotes: 0