![](/img/trans.png)
[英]How to implement Shopify - Customer Login in React-Native or JavaScript?
[英]How to Implement a graceful Login in React-native?
我是本机新手,尝试构建一个登录实现,该实现调用在aws上托管的后端api,并在api返回令牌时导航到主屏幕,并停留在登录屏幕上,如果api返回某些错误则给出错误。
我觉得我目前的逻辑和样式有点瑕疵。 我遇到的主要问题是,当我单击登录时,调用了onPress处理程序,从redux操作向api发送了一个请求,然后处理程序检查令牌是否存储在asyncStorage中。 在这种情况下,要登录,我必须按两次登录按钮,因为在第一次按此键时,调用时asyncStorage为null。 但是,如果您再次单击,那么asyncStorage会因为第一次单击而存储一些值。 我通过设置setTimeOut函数解决了此问题,但我认为这不是一个很好的解决方案。
其次,还有一些样式问题。 我还设置了一个活动指示器,但是它没有达到我想要的效果。 我希望以这样的方式合并它:单击登录时,会显示activityIndicator,并且如果登录成功,则过渡到主屏幕。 如果未成功,则会弹出警报提示问题所在。 当前,发生的情况是,当我单击具有正确凭据的登录名时,有时会显示活动指示器,而有时却没有。 如果凭据错误,则根本不会显示凭据,一秒钟后将显示警告,提示错误。
这是我的代码。
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.