Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Can';t在componentDidMount React Native中发送请求_Javascript_Reactjs_React Native_State - Fatal编程技术网

Javascript Can';t在componentDidMount React Native中发送请求

Javascript Can';t在componentDidMount React Native中发送请求,javascript,reactjs,react-native,state,Javascript,Reactjs,React Native,State,我在从componentDidMount()向后端发送请求时遇到问题。基本上,在渲染屏幕之前,我需要做两件事: 从API调用获取数据并将其保存到状态 将获得的数据发送到后端,并从后端获取响应值 我在第一步中遇到的问题是setState()是异步的,即使我的数组在console.log()数组中不是空的(我在render()和componentDidUpdate function中看到它的元素),在componentDidMount()中它也将是空的。现在,问题是:在显示屏幕之前,我仍然需要将状态

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

  • 从API调用获取数据并将其保存到状态
  • 将获得的数据发送到后端,并从后端获取响应值
  • 我在第一步中遇到的问题是setState()是异步的,即使我的数组在console.log()数组中不是空的(我在render()和componentDidUpdate function中看到它的元素),在componentDidMount()中它也将是空的。现在,问题是:在显示屏幕之前,我仍然需要将状态数组发送到后端。但是当它在那里显得空的时候,我该怎么做呢

    如果我从渲染函数中的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()
                    } />
    

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

    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);
    }
    
    如果请求确实相互依赖:

    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成为一个返回承诺的函数

    function initKit() {
      return new Promise((resolve, reject) => {
        AppleKit.initKit(
          KitPermissions.uploadBasicKitData(), 
          (err, results) => {
            if (err) reject({ error: 'InitKit failed' });
            else resolve({ data: results });
          }
        );
      });
    }
    
    function getSamples() {
      return new Promise((resolve) => {
        AppleKit.getSamples(dateFrom, (err, results) => {
          if (err) resolve([]); //rest is the same
          else resolve({ data: results });
        });
      });
    }
    
    使get samples成为一个单独的函数,返回一个承诺

    function initKit() {
      return new Promise((resolve, reject) => {
        AppleKit.initKit(
          KitPermissions.uploadBasicKitData(), 
          (err, results) => {
            if (err) reject({ error: 'InitKit failed' });
            else resolve({ data: results });
          }
        );
      });
    }
    
    function getSamples() {
      return new Promise((resolve) => {
        AppleKit.getSamples(dateFrom, (err, results) => {
          if (err) resolve([]); //rest is the same
          else resolve({ data: results });
        });
      });
    }
    
    链2背靠背承诺:如果initKit失败,它将进入
    。catch
    块,而
    getSamples
    将不会运行

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

    谢谢你的帮助,我想我现在意识到它应该如何工作了。但还有一点:如果我有两个APi请求,因此有两个承诺要返回,您会建议如何处理这些请求?谢谢您的帮助,您的方法工作得很好。最后一件事,如果我把承诺放在另一个街区里,我怎么能兑现呢?(我会更新问题)