I have an android app running on an emulator. I’m able to "log in" but I don’t get redirected to my home screen, instead, I have to reload the app on the emulator and then I am automatically logged in. The same goes for logging out..I can click a button to log out but only when I close and reopen the app am I actually logged out, if I don’t close and reopen the app just remains on the same page.
I have the following relevant snippets of code:
In App.jsx:
import React, { useEffect } from 'react'
import { AsyncStorage } from 'react-native'
import moment from 'moment'
import { NavigationContainer } from '@react-navigation/native'
import { createNativeStackNavigator } from '@react-navigation/native-stack'
import Login from './modules/Login'
import Home from './modules/Home'
import Nav from './modules/Nav'
import Events from './modules/Events/Events'
import ConsentForm from './modules/ConsentForm'
export default function App() {
const [expired, setExpired] = React.useState(true)
const [consented, setConsented] = React.useState(false)
const Stack = createNativeStackNavigator()
const getData = async () => {
return await AsyncStorage.getItem('@myapp:jwt');
}
useEffect(() => {
getData().then((value) => {
value = JSON.parse(value)
if(value == null){
setExpired(true)
}else{
const now = moment()
setExpired(now.isAfter(moment(value?.expiry)))
setConsented(value?.consented)
}
})
})
return (
<NavigationContainer>
<Stack.Navigator>
{!expired ? (
consented ? (
<>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Nav" component={Nav} />
<Stack.Screen name="Events" component={Events} />
</>
): (
<>
<Stack.Screen name="ConsentForm" component={ConsentForm} />
</>
)
) : (
<>
<Stack.Screen name="Login" component={Login} />
</>
)}
</Stack.Navigator>
</NavigationContainer>
)}
Here is my login screen:
import React from 'react'
import { *, AsyncStorage} from 'react-native' // imported a bunch of stuff here
import jwt_decode from 'jwt-decode'
import { MY_API_URL } from './constants'
const Login = ({ navigation }) => {
const [username, onChangeUsername] = React.useState(null)
const [password, onChangePassword] = React.useState(null)
const postLoginInformation = () => {
fetch(`${MY_API_URL}/login/`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: username,
password: password,
}),
})
.then(async (res) => {
const response = await res.json()
const jwt = JSON.parse(response).jwt
const decoded_jwt = jwt_decode(jwt)
await AsyncStorage.setItem(
'@myapp:jwt',
JSON.stringify(decoded_jwt),
)
}).catch((e) => console.log('login error', e, `${MY_API_URL}/login/`))
}
return (
<SafeAreaView style={styles.container}>
<!-- more page items in between -->
<TouchableOpacity
onPress={() => postLoginInformation()}
>
<Image
source={require('../images/login/login_button.png')}
/>
</TouchableOpacity>
</SafeAreaView>
)
}
export default Login
I added some console statements to see when I am logged in, however, the app doesn’t "reload" once the jwt changes – is there some way I can make it do that? Sorry if it’s obvious, this is my first react native app.
Thanks! Let me know if you need more information.
2
Answers
My suggestion is that you manually redirect to Login Screen when login process is successful. So you can do this:
You can apply the exact same logic to logout process, redirecting to login page whenever the logout process is finished successfully.
The problem here is you use
useEffect
to change value ofexpired
variable.useEffect
without any dependencies will run when any state or prop inApp.jsx
change. But the issue is nothing inApp.jsx
will change when you login, souseEffect
will not run and the screen cannot change fromLoginScreen
toHomeScreen
.I suggest you to use
redux
andreact-redux
to create a global stateexpired
and change its value.