I am trying to loop over objects which I am getting from calling an API But after setting the data in state setNodesData
and getting the data from nodesData
but when I am trying to do that I am getting an error saying: TypeError: Object.entries requires that input parameter not be null or undefined in React Native
I have also tried for(const i in nodesData)
but still I am getting an error saying expression expected
useEffect(() => {
if (apiHeaders) {
axios
.get(
"https://test-myways-anfhsya-asq.myways.in/api/****",
{
headers: apiHeaders,
}
)
.then((res) => {
console.log("API Call")
console.log(res?.data);
setNodesData(res?.data);
})
.catch((err)=>{console.log("error:",err)});
}
}, [apiHeaders]);
return (
{
Object?.entries(nodesData).forEach((i) => (
<View style={{ padding: 5 }}>
<View
style={{
flexDirection: "row",
alignItems: "center",
}}
>
<TouchableOpacity
onPress={(props) => props.navigation.navigate("CoursesPlaylistScreen")}
style={{
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
flex: 1,
}}
>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
flex: 1,
}}
>
<Text
style={{
fontSize: 16,
color: "#000000",
fontWeight: "bold",
}}
>
{i}
</Text>
</View>
</TouchableOpacity>
</View>
data:
{
"week1": {
"content": [
{
"moduleName": "HTML Crash course",
"moduleVideos": [
{
"title": "HTML Crash Course For Absolute Beginners",
"link": "https://youtu.be/*****",
"duration": "01:00:42"
}
]
},
{
"moduleName": "CSS Crash course",
"moduleVideos": [
{
"title": "CSS Crash Course For Absolute Beginners",
"link": "https://youtu.be/*****",
"duration": "01:25:11"
}
]
},
I want to get only weeks But I getting errors and I don't know how to do that.
CodePudding user response:
Change:
… Object?.entries(nodesData).map((i) => ( …
To:
… nodesData && Object.entries(nodesData).map((i) => ( …
CodePudding user response:
Issue
The issue is likely occurring on the initial render. You are attempting to convert undefined
into an array of object entries.
const [nodesData, setNodesData] = useState(); // <-- undefined initial state!
...
Object?.entries(nodesData).map( ... // <-- blows up with error
Test
const nodesData = undefined;
console.log(Object.entries(nodesData)); // error
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
const nodesData = {};
console.log(Object.entries(nodesData)); // []
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
.map
vs .forEach
Your edit when you changed Object?.entries(nodesData).map( ...
to Object?.entries(nodesData).forEach( ...
won't return anything to be rendered as .forEach
is technically a void return. Revert that change back to use .map
.
Also, since each "value" of the entry is still an object you'll need to select the object values you want to render. If there are any nested arrays, they need to also be mapped to JSX.
Solution
Provide valid initial state. An empty object should suffice.
const [nodesData, setNodesData] = useState({});
And if on the off-hand chance the nodesData
state later becomes undefined, use a null check or provide a fallback value.
nodesData && Object.entries(nodesData).map( ...
Object.entries(nodesData || {}).map( ...
Ideally though you should maintain the state invariant to at least always be a defined object.
Render the nodesData
week keys
If you just need the keys then you can:
Render the key from the entries (recall the entries is an array of key-value pairs, i.e.
[[key1, value1], [key2, value2], ...]
)Object.entries(nodesData).map(([week, data]) => ( <View style={{ padding: 5 }}> ... <Text .... > {week} // "week1", "week2", etc... </Text> ... </View>
Use
Object.keys
to get an array of just the keysObject.keys(nodesData).map((week) => ( <View style={{ padding: 5 }}> ... <Text .... > {week} // "week1", "week2", etc... </Text> ... </View>