I am trying to make two fetch requests. The second one cannot be completed until MemberId is retrieved from the first one. I have tried putting them in separate async functions but keep getting the below error.
Any insights on the best way to do this would be much appreciated.
Error message: Uncaught Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
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 Johnson`
)
.then((response) => response.json())
.then((json) => {
setMpData(json);
memberId = json.items[0].value.id;
console.log("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",
},
});
CodePudding user response:
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 Johnson`
)).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.log(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",
},
});
CodePudding user response:
This specific problem has nothing to do with the fetch
es, it is simpler.
You declared your functional component as async
:
export default async function App() {
The consequence is that it doesn't return a React element but a Promise that resolves to a React element, which React can't handle.
Remove the async
:
export default function App() {