Reputation: 495
I am sending a POST with user credentials with axios in an React-Native App:
const LoginScreen = ({ navigation }) => {
const [user, setUser] = useState('');
const [pass, setPass] = useState('');
async function onLoginPress() {
await sendtoapi(user, pass);
if(login==true){
alert('Success, redirect to Details')
navigation.navigate('Details');
}
;}
return (
<View style={{ flex: 1, alignItems: 'center'}}>
<Text style={styles.logoText}>App</Text>
<TextInput placeholder="Username" placeholderColor="#c4c3cb" style={styles.loginFormTextInput} onChangeText={user => setUser(user)} />
<TextInput placeholder="Password" placeholderColor="#c4c3cb" style={styles.loginFormTextInput} secureTextEntry={true} onChangeText={pass => setPass(pass)}/>
<Button
buttonStyle={styles.loginButton}
onPress={() => onLoginPress()}
title="Login"
/>
</View>
);
};
this is the axios function (sendtoapi):
async function sendtoapi(user, pass){
var data = JSON.stringify({"user":user,"pass":pass});
var config = {
method: 'post',
url: 'http://localhost/api/dev/',
headers: {
'Content-Type': 'application/json'
},
data : data
};
axios(config)
.then(function (response) {
var res = response.data;
if(res.login==true){
login = true;
}
})
.catch(function (error) {
console.log(error);
});
}
Basically this code works, but I have to hit the "Login" Button twice, because it seems that the var login is not set to true after await sendtoapi(user, pass); so it is not waiting. What could couse this problem?
Upvotes: 0
Views: 5480
Reputation: 35573
It is not a matter of double click in order to get the value, your sendtoapi
function is not returning a Promise (that is related to the network request).
Refactor your code so it will return axios
's Promise, then the code that handles the global login
param will run only after the server response.
function sendtoapi(user, pass) {
var data = JSON.stringify({ user: user, pass: pass });
var config = {
method: 'post',
url: 'http://localhost/api/dev/',
headers: {
'Content-Type': 'application/json',
},
data: data,
};
// --∨ this is required in order to the outer `await` will wait for the network request
return axios(config)
.then(function (response) {
var res = response.data;
return { isLoggedIn: res.login }; // it is better to return your "promised" value to the consumer
})
.catch(function (error) {
console.log(error);
});
}
small refactor to the consumer code
const LoginScreen = ({ navigation }) => {
const [user, setUser] = useState('');
const [pass, setPass] = useState('');
async function onLoginPress() {
const { isLoggedIn } = await sendtoapi(user, pass);
// ---------^ the value which your promise returns
if (isLoggedIn === true) {
alert('Success, redirect to Details');
navigation.navigate('Details');
}
}
return (
<View style={{ flex: 1, alignItems: 'center' }}>
<Text style={styles.logoText}>App</Text>
<TextInput
placeholder="Username"
placeholderColor="#c4c3cb"
style={styles.loginFormTextInput}
onChangeText={(user) => setUser(user)}
/>
<TextInput
placeholder="Password"
placeholderColor="#c4c3cb"
style={styles.loginFormTextInput}
secureTextEntry={true}
onChangeText={(pass) => setPass(pass)}
/>
<Button buttonStyle={styles.loginButton} onPress={() => onLoginPress()} title="Login" />
</View>
);
};
Tip: don't use global / module vars for such tasks since it will be hard to expose it to the rest of the app. I recommend you to store it on some react related storage (context / state).
Upvotes: 3