javascript - 无法在 componentDidMount React Native 中发送请求

标签 javascript reactjs react-native state

我在从 componentDidMount() 向后端发送请求时遇到问题。基本上我需要在渲染屏幕之前做两件事:

  1. 从API调用中获取数据并将其保存到状态
  2. 将获取的数据发送到后端并从后端获取响应值。

我在第一步遇到的问题是 setState() 是异步的,即使当我 console.log 时,我的数组不为空(我看到它是 render() 和 componentDidUpdate 函数中的元素)。 () 数组将为空。现在的问题是:在显示屏幕之前我仍然需要将该状态数组发送到后端。但是当它显示为空时我该怎么办?

如果我从渲染函数中的 Button 元素发送请求,则一切正常,但这并不完全是我所需要的。有什么建议吗?

        this.state = {
        ActivityItem: [],
        }

componentDidMount() {
    this.getDataFromKit(INTERVAL); //get data from library that does API calls
     this.sendDataToServer(); //sending to backend
 }

componentDidUpdate() {
    console.log("componentDidUpdate ", this.state.ActivityItem) // here array is not empty
}

    getDataFromKit(dateFrom) {
        new Promise((resolve) => {
        AppleKit.getSamples(dateFrom, (err, results) => {
            if (err) {
                return resolve([]);
            }
            const newData = results.map(item => {
                return { ...item, name: "ItemAmount" };
            });

            this.setState({ ActivityItem: [...this.state.ActivityItem, ...newData] })
        })
    });

最后一个:

sendDataToServer() { 
    UserService.sendActivityData(this.state.ActivityItem).then(response => {
    }).catch(error => {
        console.log(error.response);
    })

这里它按预期工作:

                 <Button
                title='send data!'
                onPress={() => this.sendDataToServer()
                } />

更新 如果我有这样的(包装在 initKit 函数中,这将返回未定义。

 AppleKit.initKit(KitPermissions.uploadBasicKitData(), (err, results) => {
        if (err) {
            return;
        }
        return new Promise((resolve) => {
            AppleKit.getSamples(dateFrom, (err, results) => {
                if (err) return resolve([]);//rest is the same

最佳答案

你必须等待 promise 解决。你需要这样的东西:

componentDidMount() {
    this.getDataFromKit(INTERVAL).then(result => {
      this.sendDataToServer(result); //sending to backend
    }).catch(e => console.error);
}

您可以更新其他获取数据的函数以返回数据:

getDataFromKit(dateFrom) {
    return new Promise((resolve) => {
        AppleKit.getSamples(dateFrom, (err, results) => {
            if (err) return resolve([]);

            const newData = results.map(item => {
                return { ...item, name: "ItemAmount" };
            });
            const allData = [ ...this.state.ActivityItem, ...newData ];
            this.setState({ ActivityItem: allData });

            resolve(allData);
        });
    });
}

最后,您需要“sendData”函数不依赖于状态,而是获取传递给它的参数:

sendDataToServer(data) { 
    UserService.sendActivityData(data).then(response => {
      // ... do response stuff
    }).catch(error => {
        console.log(error.response);
    });
}
<小时/>

处理多个请求

如果请求不相互依赖:

componentDidMount() {
  Promise.all([
    promise1, 
    promise2, 
    promise3,
  ]).then(([ response1, response2, response3 ]) => {
    // do stuff with your data
  }).catch(e => console.error);
}

如果请求确实相互依赖:

componentDidMount() {
  let response1;
  let response2;
  let response3;

  promise1().then(r => {
    response1 = r;
    return promise2(response1);
  }).then(r => {
    response2 = r;
    return promise3(response2);
  }).then(r => {
    response3 = r;

    // do stuff with response1, response2, and response3
  }).catch(e => console.error);
}
<小时/>

就您的更新而言,似乎您将异步请求包装在另一个异步请求中。我只是将它链接起来而不是包装它:

使 initKit 成为一个返回 Promise 的函数

function initKit() {
  return new Promise((resolve, reject) => {
    AppleKit.initKit(
      KitPermissions.uploadBasicKitData(), 
      (err, results) => {
        if (err) reject({ error: 'InitKit failed' });
        else resolve({ data: results });
      }
    );
  });
}

make get 采样一个返回 Promise 的单独函数

function getSamples() {
  return new Promise((resolve) => {
    AppleKit.getSamples(dateFrom, (err, results) => {
      if (err) resolve([]); //rest is the same
      else resolve({ data: results });
    });
  });
}

链 2 promise :如果 initKit 失败,它将进入 .catch block ,并且 getSamples 不会运行

componentDidMount() {
  initKit().then(kit => {
    return getSamples();
  }).then(samples => {
    // do stuff with samples
  }).catch(e => console.log);
}

关于javascript - 无法在 componentDidMount React Native 中发送请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61639355/

相关文章:

javascript - 如何以编程方式在 ember js 中的其他组件/ View 中添加组件或 View

javascript - 带有真棒字体和 jquery 的切换按钮

javascript - 获取所有阵列的独特元素 - Handlebars

javascript - Google 图表树形图工具提示中的数字格式

javascript - 如何在reactjs中清除文本框中的数据

javascript - 打开 Google 搜索屏幕,其中包含一个单词 React js

react-native - 如何在 React Native 的后台保持套接字连接处于事件状态?

react-native - 安装 chocolaty 时,“Set-ExecutionPolicy”未被识别为内部或外部命令、可运行的程序或批处理文件

javascript - API 请求错误 - 请求的资源上不存在 'Access-Control-Allow-Origin' header

react-native-testing-library:如何用act测试useEffect