I built a react code using useEffect()and Axios to get a json from an URL, however I'm getting an empty array, probably because it is not async function. Here is my code:
import axios from "axios";
import { useEffect, useState } from "react";
export function UseVacation (){
const[vacations, setVacations] = useState([]);
useEffect(() =>{
axios.get('APILINK').then( async (res) =>{
setVacations(res.data);
console.log("vactest: "+ JSON.stringify(vacations))
}).catch((err)=>{
alert("Error extracting the data from API: "+err);
})
}, [])
return (
<div>
{vacations.map( (vac) => {
<h1>{vac._id}</h1>
})}
</div>
)
}
Any idea on this?
Why dont you console res.data instead of vacations and see what it has ? Also check the network tab, and see what actual request has in the response
I've changed my return and it fixed issue. Why? I don't know, but is working:
return (
<div>
{vacations.map( (vac) => {
return(
<h1>{vac?._id}</h1>
)
})}
</div>
)
Have you tried the following?
return (
<div>
{vacations && vacations.map( (vac) => {
<h1>{vac._id}</h1>
})}
</div>
)
I have good suggestion for you:
const[vacations, setVacations] = useState([]);
useEffect(() => {
const getApi = async () => {
try {
const res = await axios.get('APILINK')
setVacations(res.data);
} catch(error) {
console.log(error)
}
}
getApi()
}, [])
console.log("vactest: "+ vacations)
I cannot explain but if you set state in useEffect and direct log state in useEffect, it only log previous state
Related
I want to fetch data from given API(link is censored in code example), but cant manage to to display product.name from my Api fetch.
import { useState, useEffect } from "react";
import axios from "axios";
function DataFetching() {
const [posts, setPosts] = useState([]);
useEffect(() => {
axios
.get("https://CENSORED/")
.then((res) => {
console.log(res);
setPosts(res.data);
})
.catch((err) => {
console.log(err);
});
}, []);
return (
<div>
<div>
{posts.map((post) => (
<h1>{post.product.name}</h1>
))}
</div>
</div>
);
}
Errors
The error is because the posts array is empty initially you need to check first if the array has some data then perform a map
setPosts(res.data.product)
{posts?.map((post) => (
<h1>{post.name}</h1>
))}
or you can use conditional like this
{ posts.length > 0
? posts.map((post) => (
<h1>{post.name}</h1>
))
: <Your custom message/>
}
res.data is indicated to be an object in the console.log. the map method will only work on arrays. If you were expecting an array, make sure you aren't hitting the "detail" endpoint, which would return specific information about a post.
I'm trying to get data from Axios but while the data is being fetch the return statement gets executed, I think.
import axios from 'axios'
import React, { useState, useEffect} from 'react'
export default function Overall() {
const [post, setPost] = useState({
date:null,
total:null
});
useEffect(() => {
async function fetchData(){
await axios.get(`https://data.covid19india.org/v4/min/data.min.json`).then((response) => {
console.log("Inside Then block");
setPost({'total':Object.entries(response.data).map(([k,v])=>
// console.log(k,v.meta.last_updated,v.total.confirmed)
v.total.confirmed
).reduce((prev, curr)=>prev+curr,0)
})
setPost({'date':Object.entries(response.data)[0][1].meta.last_updated})
});
}
fetchData()
console.log("Data Fetched");
}, []);
console.log("Post: ",post);
return (
<div className='overall-container'>
<div>
<h2>India</h2>
</div>
<div>
<h2>Total: {post.total}</h2>
<h2>Date: {post.date}</h2>
</div>
</div>
)
}
The problem is that in return only {post.date} is working while {post.curr} is not. I don't know why? I'm new to react so I don't know much. I would appreciate if someone could explain this.
I'm assuming that you meant {post.total} instead of {post.curr}
You could change from:
setPost({'total':Object.entries(response.data).map(([k,v])=>
// console.log(k,v.meta.last_updated,v.total.confirmed)
v.total.confirmed
).reduce((prev, curr)=>prev+curr,0)
})
setPost({'date':Object.entries(response.data)[0][1].meta.last_updated})
To:
setPost({
total: Object.entries(response.data).map(([k,v])=>
// console.log(k,v.meta.last_updated,v.total.confirmed)
v.total.confirmed
).reduce((prev, curr)=>prev+curr,0),
date: Object.entries(response.data)[0][1].meta.last_updated
});
And it should work. However, maybe it'd be better to seperate date and total into two different states?
This is a bad practice to do async stuff in useEffect. You should create a separate function and call it from useEffect.
Your error is caused because you call setPost to update total and then once again to update date.
When you call setPost it will erase previous value for post. If you need to keep previous value you can do:
setPost((prev) => ({
...prev,
date: new Date()
}));
In your code you should call setPost only once
import React, { useState, useEffect} from 'react'
import axios from 'axios'
export default function Overall() {
const [post, setPost] = useState({});
const fetchData = async () => {
try {
const response = await axios.get(`https://data.covid19india.org/v4/min/data.min.json`)
// tranform your response and then set it to state at once
const total = 1 // replace with your total
const date = new Date() // replace with your date
setPost({ total, date })
} catch(err) {
console.log(err);
}
}
useEffect(() => {
fetchData()
}, []);
console.log("Post: ",post);
return (
<div className='overall-container'>
<div>
<h2>India</h2>
</div>
<div>
<h2>Total: {post?.total}</h2>
<h2>Date: {post?.date}</h2>
</div>
</div>
)
}
I'm new to react, I'm getting this error constantly and after google some I can't find the reason why the useState value can't be read as array :( ... this the error I'm getting: 'TypeError: team.map is not a function'
import React, { useEffect, useState } from "react";
const SportTeams = () => {
const [team, setTeam] = useState([]);
useEffect(() => {
const getSports = async () => {
const response = await fetch("https://www.thesportsdb.com/api/v1/json/1/all_sports.php");
const data = await response.json();
setTeam(data);
console.log(data);
}
getSports();
}, []);
return (
<div className="myClass">
<ul>
{team.map((sport, index) => {
return <li key={`${sport.strSport}-${index}`}>{sport.strSport}</li>
})}
</ul>
</div>
);
};
export default SportTeams;
Just update setTeam like following, your error will be resolved.
setTeam(data.sports);
It is because you are setting the team state with the data without checking if its undefined. If the data is undefined your state team become undefined as well. So make sure to check the data.
import React, { useEffect, useState } from "react";
const SportTeams = () => {
const [team, setTeam] = useState([]);
useEffect(() => {
const getSports = async () => {
const response = await fetch("https://www.thesportsdb.com/api/v1/json/1/all_sports.php");
if (response) {
const data = await response.json();
if (data) {
setTeam(data);
}
}
console.log(data);
}
getSports();
}, []);
return (
<div className="myClass">
<ul>
{team.map((sport, index) => {
return <li key={`${sport.strSport}-${index}`}>{sport.strSport}</li>
})}
</ul>
</div>
);
};
export default SportTeams;
There might also be the chance that your response is not what you expected and the actual data might be inside your response. In that case you need check what your response first then proceed to set the data.
As I said in my comment. the value you are setting to teams isn't an array.
const data = await response.json();
setTeam(data.sports);
I'm making a simple API call from a react component to my Mongo database, which returns a list of items.
Inside useEffect, I'm making a GET request to return an arrays of reviews. When I log the resulting to the data, I'm seeing the correct information:
useEffect(() => {
axios.get('http://localhost:3000/all-reviews')
.then((allReviews) => {
console.log(allReviews)
})
})
However, when I try to set state inside the useEffect method, my program breaks. I know that setState is async, so how do I configure it so it works inside useEffect?
Here's the entire component used to control API calls:
App.jsx
import React, {useState, useEffect} from 'react'
import axios from 'axios'
const App = () => {
const [reviews, setReviews] = useState([])
useEffect(() => {
axios.get('http://localhost:3000/all-reviews')
.then((allReviews) => {
setReviews(allReviews)
})
})
return (
<>
<h1>React development has begun!</h1>
{
reviews.map((item, index) => {
<h1>item.title</h1>
})
}
</>
)
}
export default App
Not that relevant, but here's the route this component invokes:
server.get('/all-reviews', (req,res) => {
Review.find()
.then((result) => {
res.send(result)
})
.catch(err => {
console.log(err)
})
})
I think firstly, your useEffect doesn't have a depedency, which mean it will run every time, it needs an empty array at least, like the one below.
useEffect(() => {
},[])
And when you are expecting a JSON data in React, you have to check if the data is available first before populating it, if not react will freak out.
You could do this.
return (
<>
<h1>React development has begun!</h1>
{
reviews?.map((item, index) => {
<h1>item.title</h1>
})
}
</>
)
}
or this
return (
<>
<h1>React development has begun!</h1>
{
reviews && (reviews.map((item, index) => {
<h1>item.title</h1>
}))
}
</>
)
}
and thirdly you are not returning anything in your dom.
it should be this way.
reviews && (reviews.map((item, index) =>
<h1>item.title</h1>
))
or if you wanna do it your way, you could just do this.
reviews && (reviews.map((item, index) => {
return (
<h1>item.title</h1>
)
}))
I am new to react hooks. I am trying to cast API response into an array using react useState hook. It's giving me empty with the below approach
const [post, setPostArray] = useState([]);
useEffect(() => {
const postparams = { userList: result };
axios
.get(environment._urlPosts, { headers, params: postparams })
.then(posts => {
// storing response data in array
setPostArray(posts.data.post);
console.log(post);
})
.catch(err => {});
}, []);
Then I used the below approach and I was able to see data is printing in the console log
axios.get(environment._urlPosts, { headers, params: postparams }).then(posts => {
// storing response data in array
for (let obj of posts.data.post) {
post.push(obj)
}
setPostArray(post)
console.log(post)
But when I try to iterate this post array in my JSX, it's giving me empty array.
</div>
{/* array length */}
{post.length}
{post.map(post =>
<div className="card">
<Post username={post.username} fullname={post.fullname} postedTime={post.postedTime} postContent='Hi' tweeterLike={post.tweeterLike} />
</div>
)}
Can you please help me to resolve this?
Here is a minimal Example of what you are trying to achieve.
This is the working code:
import React, {useEffect, useState} from "react";
import "./styles.css";
export default function App() {
const [post, setPostArray] = useState([])
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => {
console.log(json);
setPostArray([json]);
})
// setPostArray([{name: 'a'}, {name: 'b'},{name: 'c'}])
},[])
console.log(post)
return (
<div className="App">
{
post.map(item => <div>{item.title} </div>)
}
</div>
);
}
Here is the link to the example in codeSandBox: https://codesandbox.io/s/jovial-snow-773kp