繁体   English   中英

如何在React-native中实现优美的登录?

[英]How to Implement a graceful Login in React-native?

我是本机新手,尝试构建一个登录实现,该实现调用在aws上托管的后端api,并在api返回令牌时导航到主屏幕,并停留在登录屏幕上,如果api返回某些错误则给出错误。

我觉得我目前的逻辑和样式有点瑕疵。 我遇到的主要问题是,当我单击登录时,调用了onPress处理程序,从redux操作向api发送了一个请求,然后处理程序检查令牌是否存储在asyncStorage中。 在这种情况下,要登录,我必须按两次登录按钮,因为在第一次按此键时,调用时asyncStorage为null。 但是,如果您再次单击,那么asyncStorage会因为第一次单击而存储一些值。 我通过设置setTimeOut函数解决了此问题,但我认为这不是一个很好的解决方案。

其次,还有一些样式问题。 我还设置了一个活动指示器,但是它没有达到我想要的效果。 我希望以这样的方式合并它:单击登录时,会显示activityIndi​​cator,并且如果登录成功,则过渡到主屏幕。 如果未成功,则会弹出警报提示问题所在。 当前,发生的情况是,当我单击具有正确凭据的登录名时,有时会显示活动指示器,而有时却没有。 如果凭据错误,则根本不会显示凭据,一秒钟后将显示警告,提示错误。

这是我的代码。

login.js

    const {width: WIDTH} = Dimensions.get('window')
    class Login extends Component {

        state = {
            controls: {
                email: {
                    value: "",
                    valid: true,
                    validationRules: {
                        isEmail: true
                    }
                },
                password: {
                    value: "",
                    valid: true,
                    validationRules: {
                        minLength: 6
                    }
                }
            },
            loading: false
        }

        async componentDidMount() {

            let authToken = await AsyncStorage.getItem("auth-token")
            console.log(authToken);
            this.props.onAutoSignIn();

            this.props.navigation.navigate(authToken !== null ? 'MAIN_STACK' : 'LOGIN')

            /* if (authToken){
                this.props.navigation.navigate(this.props.token == null ? 'MAIN_STACK' : 'LOGIN')
            } */

        }

        updateInputState = (key, value) => {
            this.setState(prevState => {
                return{
                    controls: {
                        ...prevState.controls,
                        [key]:{
                            ...prevState.controls[key],
                            value: value
                        }
                    }
                }
            })
        }

        loginRequest = async () => {
            try{
                this.state.loading=true;
                const authData = {
                    email: this.state.controls.email.value,
                    password: this.state.controls.password.value
                }


                this.props.onLogin(authData);

                //let authToken = await AsyncStorage.getItem("auth-token")

                setTimeout(async () => {
                    let authToken = await AsyncStorage.getItem("auth-token");
                    console.log(authToken);
                    this.state.loading=false;
                    this.props.navigation.navigate(authToken !== null ? 'MAIN_STACK' : 'AUTH');

                    }, 2000);


                //console.log(authToken);

                //this.props.navigation.navigate(authToken !== null ? 'MAIN_STACK' : 'AUTH');



            }
            catch(err){
                console.log(err)
            }

        }

        render() {

            return (

            <View style={styles.base}>   
            <ImageBackground style={styles.container} source={img}>
                <KeyboardAvoidingView style={styles.containerKeyboard}>

                    <Image style={styles.logoContainer} source={imgLogo}/>



                    <View style={styles.inputContainer}>
                        <TextInput 
                        style={styles.input}
                        placeholder="Email"
                        placeholderTextColor= {'white'}
                        //underlineColorAndroid= 'transparent'
                        value={this.state.controls.email.value}
                        onChangeText={(val) => this.updateInputState("email",val)} 

                        />
                    </View>

                    <View style={styles.inputContainer}>
                        <TextInput 
                        placeholder="Password"
                        placeholderTextColor= {'white'}
                        //underlineColorAndroid='transparent'
                        secureTextEntry={true}
                        value={this.state.controls.password.value}
                        onChangeText={(val) => this.updateInputState("password",val)} 
                        style={styles.input}
                        />
                    </View>





                    <TouchableHighlight style={styles.loginButton} 
                                    onPress={this.loginRequest}>
                            <Text style={styles.loginText}>Log In</Text>
                    </TouchableHighlight>

                    {this.state.loading &&
                        <View style={styles.loading} pointerEvents="none" >
                            <ActivityIndicator size='large' />
                        </View>
                    }

                </KeyboardAvoidingView>
            </ImageBackground>
            </View>
            )
        }
    }

    const styles = StyleSheet.create({

        base: {
            flex:1
        },

        container: {
            flex: 1,
            //padding: 26,
            //backgroundColor: "black",
            alignItems: "center",
            justifyContent: "center"
        },
        logoContainer: {
            width: 150,
            height: 150,
            position: 'absolute',
            top: 50

        },
        containerKeyboard: {
            flex:1,
            //padding: 26,
            //backgroundColor: "black",
            alignItems: "center",
            justifyContent: "center"
        },
        inputContainer: {
            width: WIDTH-55,
            //borderBottomColor: '#F5FCFF',
            //borderBottomColor: 'red',
            borderRadius: 15,
            borderColor: '#ffffff',
            borderWidth: 1.5,
            backgroundColor: 'black',
            //backgroundColor: "#fff",
            //backgroundColor:'yellow',
            //borderBottomWidth: 1,
            marginBottom:20,
            flexDirection: 'row',
            alignItems:'center',
            opacity:.4


        },
        input: {
            width: WIDTH - 58,
            //height: 55,

            borderRadius: 13,
            fontSize: 16,
            paddingLeft: 45,
            backgroundColor: 'black',
            color: 'white'



        },
        loginButton_image: {
            width: 135,
            height: 50,
            position: 'absolute',
            bottom: 65,
        // opacity: .5,
            //borderRadius: 30



        },


        loginButton: {
            //height:45,
            width: 100,
            justifyContent: 'center',
            alignItems: 'center',
            position: 'absolute',
            bottom: 100,
            opacity: .5 ,
            borderWidth: 2,
            borderColor: 'yellow',
            borderRadius: 10,
            padding: 10
            //marginTop:350,
            //width:250,
            //backgroundColor: "#00b5ec",
        },
        loginText: {
            color: 'yellow',
            fontWeight: 'bold'
        },

        loading: {
            position: 'absolute',
            left: 0,
            right: 0,
            top: 0,
            bottom: 0,
            alignItems: 'center',
            justifyContent: 'center',
            backgroundColor: 'black'
        }

    })

    const mapStateToProps = (state) => {

        return {
            token: state.login.token
        }
    }

    const mapDispatchToProps = (dispatch) => {

        return {
            onLogin: (authData) => {dispatch(authLogin(authData))},
            onAutoSignIn: () => {dispatch(authGetToken())}
        }
    }

    export default connect (mapStateToProps, mapDispatchToProps)(Login);

action.js

    export const authLogin = (authData) => {
        return dispatch => {
            let url = "http://ec2-54-169-225-146.ap-southeast-1.compute.amazonaws.com:8000/api/auth/login/";
            let body = JSON.stringify({
                username: authData.email,
                password: authData.password

            })
            return fetch(url, {
                method: "POST",
                body: body,
                headers: {
                "Content-Type": "application/json"
                }
            })

            .then((res) => { return res.json() })
            .then((parsedRes) => {
                console.log(parsedRes)
                if (parsedRes.error) {
                    console.log("Authentication failed, please try again!");
                    throw parsedRes.error

                } else {
                    dispatch(authStoreToken(parsedRes.token))
                    return true
                }

            })
            .catch(err => {
                console.log("ithaaay takooos")
                console.log(err);
                alert('Authentication Failed, Please Try Again!')
            })
        }
    }

    export const authStoreToken = token => {
        return dispatch => {
            dispatch(authSetToken(token));
            AsyncStorage.setItem("auth-token", token)
        }
    }

如果有人可以给我一些指导,我将不胜感激。 我的意思是我正在做我想做的事,但这一点都不优雅

是的,您做错了。 setTimeout导致了问题,而不是很好的解决方案。 从loginRequest函数中删除它。 并且在authStoreToken中成功登录后,您将分派authSetToken,因此我假设这将作为结果调用componentDidUpdate生命周期方法的结果更新令牌。 在这里,您可以检查登录组件的令牌属性是否具有某些值,然后像这样进行导航。 this.props.navigation.navigate(this.props.token!== null?'MAIN_STACK':'AUTH');

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM