Не удается отправить запрос в componentDidMount React Native - PullRequest
0 голосов
/ 06 мая 2020

У меня проблема с отправкой запроса на серверную часть из моего componentDidMount (). В основном, перед рендерингом экрана мне нужно сделать две вещи:

  1. Получить данные из вызова API и сохранить их в состоянии
  2. Отправить полученные данные в бэкэнд и принять значения ответа из бэкэнда.

Проблема, с которой я столкнулся на первом этапе, заключается в том, что setState () имеет значение asyn c, и хотя мой массив не пустой (я вижу его элементы в функциях render () и componentDidUpdate) в componentDidMount () когда я использую массив console.log (), он будет пустым. Теперь проблема заключается в следующем: мне все еще нужно отправить этот массив состояний в бэкэнд, прежде чем показывать экран. Но как я могу это сделать, когда он там кажется пустым?

У меня все работает нормально, если я отправляю запрос из элемента 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, это вернет undefined.

 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

1 Ответ

1 голос
/ 06 мая 2020

вам нужно дождаться разрешения обещания. Вам нужно что-то вроде этого:

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);
}

что касается вашего обновления, похоже, вы завернули свой asyn c запрос в другой асинхронный c запрос. Я бы просто связал его вместо того, чтобы обернуть его:

сделать initKit функцией, которая возвращает обещание

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 samples отдельной функцией, которая возвращает обещание

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

цепочка 2 обещает подряд: если initKit завершится неудачно, он будет go в блоке .catch и getSamples не запустится

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