首页 > 解决方案 > 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 ;所以它不等待。什么会导致这个问题?

标签: reactjsreact-nativeaxios

解决方案


这不是为了获取值而双击的问题,您的sendtoapi函数没有返回 Promise(与网络请求有关)。

重构您的代码,使其返回axiosPromise,然后处理全局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>
  );
};

提示:不要将全局/模块变量用于此类任务,因为很难将其暴露给应用程序的其余部分。我建议您将其存储在一些与反应相关的存储(上下文/状态)上。


推荐阅读