Я пытаюсь сделать два запроса на выборку. Второй не может быть завершен, пока 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",
},
});
Эта ошибка обычно возникает, когда элемент представления пытается отобразить объект, так как представление всегда должно содержать значения, а не объекты. Ниже я дал ответ о том, как можно упростить вызов API еще на один шаг.
Проблема, похоже, не в выборке, а в рендеринге. Поскольку я не знаю точной структуры данных, мне будет сложно понять, что именно идет не так. Но если бы я предположил, проблема может быть с датами, т.е. если они являются объектами даты, а затем преобразовать их в строку с помощью методов .toString.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


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