我的react本机应用程序有问题。它总是在登录屏幕上打开,但我想在用户已经登录时打开主屏幕。我正在使用AsyncStorage来验证令牌是否为null。如果令牌为空,我会将状态屏幕设置为"登录",如果不是,我会设置状态屏幕为"主"。但我认为导航器是在状态更改之前返回的。但我不知道如何以正确的方式来做。请帮帮我!
我的导航器(我使用的是react navigation v5(
import React, {PureComponent} from 'react'
import { createStackNavigator } from '@react-navigation/stack'
import { NavigationContainer } from '@react-navigation/native'
import AsyncStorage from '@react-native-community/async-storage'
import { connect } from 'react-redux'
import Login from '../screens/Login'
import Register from '../screens/Register'
import Main from '../screens/Main'
import TransactionRegistration from '../screens/TransactionRegistration'
import { renewLogin } from '../store/actions/user'
import '../config/ReactotronConfig'
const StackMain = createStackNavigator()
class Navigator extends PureComponent {
state = {
screen: 'Login',
}
componentDidMount() {
this.isLogged()
.then(res => this.setState({ screen: res}))
.catch(err => alert('An error occurred'))
}
isLogged = async() => {
let token = await AsyncStorage.getItem('@user_token')
let id = await AsyncStorage.getItem('@user_id')
const user = {
id: id,
token: token
}
if (token !== null) {
await this.props.onRenewLogin(user)
return 'Main'
}
else {
return 'Login'
}
}
render() {
return (
<NavigationContainer>
<StackMain.Navigator initialRouteName={this.state.screen}>
<StackMain.Screen
component={Login}
name='Login'
options={{headerShown: false}} />
<StackMain.Screen
component={Register}
name='Register'
options={{headerShown: false}} />
<StackMain.Screen
component={Main}
name='Main'
options={{headerShown: false}} />
<StackMain.Screen
component={TransactionRegistration}
name='TransactionRegistration'
options={{headerShown: false}} />
</StackMain.Navigator>
</NavigationContainer>
)
}
}
const mapDispatchToProps = dispatch => {
return {
onRenewLogin: user => dispatch(renewLogin(user)),
}
}
export default connect(null, mapDispatchToProps)(Navigator)
我的登录屏幕(当登录成功时,请查看我导航到Main(
import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import {
login,
} from '../../store/actions/user'
import {
View,
Text,
Animated,
StatusBar,
} from 'react-native'
import { validateForm } from '../../common/utils/validators'
import AuthContainer from '../../components/Auth/AuthContainer'
import AuthTitle from '../../components/Auth/AuthTitle'
import AuthButton from '../../components/Auth/AuthButton'
import AuthInput from '../../components/Auth/AuthInput'
import AuthHeader from '../../components/Auth/AuthHeader'
import SpeechBubble from '../../components/Auth/SpeechBubble'
import styles from '../../assets/css/styles'
import { colors } from '../../assets/css/colors'
class Login extends PureComponent {
state = {
email: '',
password: '',
text: 'Olá! Cadastrou sua conta usando e-mail e senha? Insira-os aqui:',
messageError: '',
shakeAnimation: new Animated.Value(0),
formError: false,
}
componentDidUpdate = (prevProps, prevState) => {
if(prevProps.isLoading && !this.props.isLoading && this.props.token){
this.props.navigation.navigate('Main')
}
if(prevProps.loginError != this.props.loginError && this.props.loginError != ''){
this.setState({ text: this.props.loginError, formError: true})
}
if(prevState.text != this.state.text){
this.handleAnimation()
}
}
login = async() => {
this.setState({messageError: validateForm('login', this.state)})
if (this.state.messageError == '') {
await this.props.onLogin({ ...this.state })
if (this.props.loginError != '') {
this.setState({ text: this.props.loginError, formError: true})
this.handleAnimation()
}
}
else {
this.setState({text: this.state.messageError, formError: true})
this.handleAnimation()
}
}
navigateToRegister = () => {
this.props.navigation.navigate('Register')
}
handleAnimation = () => {
Animated.sequence([
Animated.timing(this.state.shakeAnimation, { toValue: 10, duration: 80, useNativeDriver: true }),
Animated.timing(this.state.shakeAnimation, { toValue: -10, duration: 80, useNativeDriver: true }),
Animated.timing(this.state.shakeAnimation, { toValue: 10, duration: 80, useNativeDriver: true }),
Animated.timing(this.state.shakeAnimation, { toValue: 0, duration: 80, useNativeDriver: true })
]).start()
}
render(){
return (
<AuthContainer>
<StatusBar backgroundColor={colors.screenBg} barStyle='dark-content' />
<AuthHeader />
<SpeechBubble>
<Animated.View
style={{ transform: [{translateX: this.state.shakeAnimation}] }}>
<AuthTitle
text={this.state.text}
styleTitle={!this.state.formError ? [styles.loginFont, styles.bodyText] :
[styles.loginFont, styles.bodyText, styles.bodyTextError]}/>
</Animated.View>
<AuthInput
placeholder='Seu e-mail'
keyboardType='email-address'
autoFocus={true}
autoCorrect={false}
autoCapitalize='none'
returnKeyType='next'
value={this.state.email}
onChangeText={email => this.setState({ email })}
blurOnSubmit={false} />
<AuthInput
placeholder='Sua senha'
returnKeyType='go'
value={this.state.password}
password={true}
onChangeText={password => this.setState({ password })} />
<AuthButton title='Entrar' onPress={() => this.login()}/>
<View style={styles.bodyBottom}>
<Text style={[styles.loginFont, styles.bodyLink]}>Esqueci minha senha</Text>
<Text style={[styles.loginFont, styles.bodyLink]} onPress={this.navigateToRegister}>
Ainda não cadastrei uma conta
</Text>
</View>
</SpeechBubble>
</AuthContainer>
)
}
}
const mapStateToProps = ({ user }) => {
return {
isLoading: user.isLoading,
token: user.token,
loginError: user.loginError,
}
}
const mapDispatchToProps = dispatch => {
return {
onLogin: user => dispatch(login(user)),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Login)
您在第一次渲染时是对的,initialRouteName是Login,如果您将其更改为已渲染登录的状态也没关系,更简单的解决方法是在登录时实际初始化应用程序,然后使用导航道具方法navigation将用户发送到预期屏幕。
因此,在您的组件DidMount 中
componentDidMount = () => {
this.isLogged()
.then(res => {
this.props.navigation.navigate(res);
})
.catch(err => alert('An error occurred'))
}