Fetch внутри Fetch — объекты недействительны в качестве дочернего элемента React

Я пытаюсь сделать два запроса на выборку. Второй не может быть завершен, пока MemberId не будет получен из первого. Я попытался поместить их в отдельные асинхронные функции, но продолжаю получать следующую ошибку.

Любые идеи о том, как лучше всего это сделать, будут высоко оценены.

Сообщение об ошибке: Неперехваченная ошибка: объекты недействительны в качестве дочерних элементов React (найдено: [object Promise]). Если вы хотели отобразить коллекцию дочерних элементов, используйте вместо этого массив.

import { StatusBar } from "expo-status-bar";
import { useEffect, useState } from "react";
import { StyleSheet, Image, Text, View } from "react-native";

export default async function App() {
  const [isLoading, setLoading] = useState(true);
  const [isLoadingMp, setLoadingMp] = useState(true);
  const [data, setData] = useState([]);
  const [mpData, setMpData] = useState([]);
  let memberId = 0;

  useEffect(() => {
    fetch(
      `https://members-api.parliament.uk/api/Members/Search?Name=Boris%20Johnson`
    )
      .then((response) => response.json())
      .then((json) => {
        setMpData(json);
        memberId = json.items[0].value.id;
        console.info("memberId:", memberId);
      })
      .catch((error) => console.error(error))
      .then(
        fetch(
          `https://commonsvotes-api.parliament.uk/data/divisions.json/membervoting?memberId=${memberId}`
        )
          .then((response) => response.json())
          .then((json) => setData(json))
          .catch((error) => console.error(error))
          .finally(() => setLoading(false))
          .finally(() => {
            setLoadingMp(false);
          })
      );
  });

  return (
    <View style = {{ flex: 1, padding: 24 }}>
      {isLoading || isLoadingMp ? (
        <Text>Loading...</Text>
      ) : (
        <View style = {styles.container}>
          <Text>
            <Image
              source = {{
                uri: `${mpData.items[0].value.thumbnailUrl}`,
                width: 60,
                height: 60,
              }}
            />
            <Text>{`${mpData.items[0].value.id}\n`}</Text>

            {data.map((individualData) => {
              return `\nDate: ${
                individualData.PublishedDivision.Date
              }\nDivision id: ${
                individualData.PublishedDivision.Date
              }\nDivision title: ${
                individualData.PublishedDivision.Title
              }\nVoted: ${!!individualData.MemberVotedAye ? "Yes" : "No"}\n`;
            })}
          </Text>
          <StatusBar style = "auto" />
        </View>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
});

одна проблема заключается в том, что .then ожидает функцию в качестве аргумента, тогда как вы вызываете выборку напрямую, и поэтому memberId еще не будет установлен, поскольку «внутренняя» выборка вызывается слишком рано ... быстрое исправление .then(() => fetch( .... etc

Jaromanda X 25.11.2022 01:19

Эта ошибка обычно возникает, когда элемент представления пытается отобразить объект, так как представление всегда должно содержать значения, а не объекты. Ниже я дал ответ о том, как можно упростить вызов API еще на один шаг.

Bipin 25.11.2022 02:14

Проблема, похоже, не в выборке, а в рендеринге. Поскольку я не знаю точной структуры данных, мне будет сложно понять, что именно идет не так. Но если бы я предположил, проблема может быть с датами, т.е. если они являются объектами даты, а затем преобразовать их в строку с помощью методов .toString.

dev404 25.11.2022 02:55
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
3
85
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий
import { StatusBar } from "expo-status-bar";
import { useEffect, useState } from "react";
import { StyleSheet, Image, Text, View } from "react-native";

export default function App() {
  const [isLoading, setLoading] = useState(true);
  const [isLoadingMp, setLoadingMp] = useState(true);
  const [data, setData] = useState([]);
  const [mpData, setMpData] = useState([]);
  let memberId = 0;

  useEffect(() => {
    const callApi = async ()=>{//defining a async function to call the API
      
      setLoading(true);//maybe you just need one loading flag
      try{

      const result = await (await fetch(
      `https://members-api.parliament.uk/api/Members/Search?Name=Boris%20Johnson`
      )).json();//first api and json() its result
      const memberId = result.items[0].value.id;//get the member id from it
      
      const finalResult = await(await fetch(
          `https://commonsvotes-api.parliament.uk/data/divisions.json/membervoting?memberId=${memberId}`
        )).json();//second api call and json() its result
        //set the state
        setData(finalResult);
        setMpData(result);
      }catch(e){
        console.info(e)
      }finally{
          setLoading(false);//set loading false in both the fail and success case
      }
    }
    callApi();//calling the function
  }, []);

 //VIEW rendering
  return (<View style = {{ flex: 1, padding: 24 }}>
      {isLoading ? (
        <Text>Loading...</Text>
      ) : (
        <View style = {styles.container}>
          <Text>
            <Image
              source = {{
                uri: `${mpData.items[0].value.thumbnailUrl}`,
                width: 60,
                height: 60,
              }}
            />
            <Text>{`${mpData.items[0].value.id}\n`}</Text>

            {data.map((individualData) => {
              return `\nDate: ${
                individualData.PublishedDivision.Date
              }\nDivision id: ${
                individualData.PublishedDivision.Date
              }\nDivision title: ${
                individualData.PublishedDivision.Title
              }\nVoted:  ? "Yes" : "No"}\n`;
            })}
          </Text>
          <StatusBar style = "auto" />
        </View>
      )}
    </View>);
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
});

Эта конкретная проблема не имеет ничего общего с fetches, она проще.

Вы объявили свой функциональный компонент как async:

export default async function App() {

Следствием этого является то, что он возвращает не элемент React, а Promise, который разрешается в элемент React, который React не может обработать.

Удалите async:

export default function App() {

Другие вопросы по теме