reactjs - React Native Axios -> 等待异步响应,如果为真则导航到新页面
问题描述
我在 React-Native 应用程序中使用 axios 发送带有用户凭据的 POST:
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>
);
};
这是 axios 函数(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);
});
}
基本上这段代码有效,但我必须点击“登录”按钮两次,因为在await sendtoapi(user, pass);之后似乎var login没有设置为 true ;所以它不等待。什么会导致这个问题?
解决方案
这不是为了获取值而双击的问题,您的sendtoapi
函数没有返回 Promise(与网络请求有关)。
重构您的代码,使其返回axios
Promise,然后处理全局login
参数的代码将仅在服务器响应后运行。
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);
});
}
对消费者代码的小重构
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>
);
};
提示:不要将全局/模块变量用于此类任务,因为很难将其暴露给应用程序的其余部分。我建议您将其存储在一些与反应相关的存储(上下文/状态)上。
推荐阅读
- visual-studio-code - vs 代码扩展可以更改 vs 代码设置吗?
- go - 在这个例子中爬虫多线程是如何工作的?
- spring - 使用多个内存数据库进行 Spring Boot / JUnit 集成测试
- linux - Linux 进程处于活动状态,但关联的 jar 已关闭
- python - 构建数据集 - np 数组上的奇怪行为
- swift - 无法从枚举中获取原始字符串
- bash - 如何删除管道中的每个第二个字节?
- android - SensorManager.getOrientation 的实际俯仰和横滚返回范围是多少?
- java - Hibernate 在为多对一记录保存记录时遇到额外的查询
- label - 使用 LabelMe Dataset 创建 tf.data 进行图像分割