Hello i take data from realtime database in firebase with this way.
useEffect(() => {
async function asyncCall() {
const myurl = await axios.get("https://mysiteproject- 8adcf.firebaseio.com/products.json")
setUrl(myurl)
}
asyncCall();
},[]);
The result of when i
console.log(url)
showing in the below image
When i
console.log(url.data)
this is shown up
That is the data i want to map. But when i
console.log(url.data.id)
this is shown up in my console
Can anyone tell me why this happening.
Also i try this in my code
useEffect(() => {
async function asyncCall() {
const myurl = await axios.get("https://mysiteproject-8adcf.firebaseio.com/products.json")
setUrl(myurl)
}
asyncCall();
},[]);
let myvar = url.data;
console.log(myvar);
{myvar.map((myvar => (
console.log(myvar.id)
)))}
But again i have a error
Can anyone help me with this??
You should add check if url.data is exists. When you render console.log(myvar); - url.data is undefined because you didn't get it from the server yet. So your code should looks like this:
useEffect(() => {
async function asyncCall() {
const myurl = await axios.get(
"https://mysiteproject-8adcf.firebaseio.com/products.json"
);
setUrl(myurl);
}
asyncCall();
}, []);
if (url.data) {
let myvar = url.data;
console.log(myvar);
myvar.map((myvar) => console.log(myvar.id));
}
When you'll get url.data the component will be updated because you update state via setUrl and the data will be logged to console.
Related
I'm building a blog app and I want to list all the posts stored in MongoDB. Each post object has an author id, and I want to get the posts and then get the author name of each post and add it as an attribute to the post object.
I defined the methods getUserById and getPosts to make api calls to a Node.js backend, and they both work fine.
Now I'm doing something like this in the useEffect hook of the component, which does not work properly:
useEffect(() => {
const fetchPosts = async () => {
const res = await getPosts();
let posts = res.data;
posts.map(async (post) => {
const res = await getUserById(post.userId);
post.username = res.data.username;
});
setPosts(posts);
};
fetchPosts();
}, []);
I'm wondering what is the proper way to implement something like this. Thanks.
Let add async to effects function and await for fetchPosts():
useEffect(async () => {
const fetchPosts = async () => {
const res = await getPosts();
let posts = res.data;
posts.map(async (post) => {
const res = await getUserById(post.userId);
post.username = res.data.username;
});
setPosts(posts);
};
await fetchPosts();
}, []);
I am using gitbeaker to get a project from gitlab API, after fetching the project, I used useState to save the project object, now I want to fetch another API whose URL is in that object, but whenever I try to access that URL, an error appears "Cannot read property 'issues' of undefined".
Here's my code:
const [project, setProject] = useState<any>({});
const api = new Gitlab({
host: "https://example.com",
token: "my token",
});
useEffect(() => {
(async () => {
const projectsPromises = await api.Projects.all().then((allprojects) => {
return allprojects;
});
Promise.all(projectsPromises).then((data) => {
setProject(data.find((element) => element.id === 338));
});
})();
return () => {};
}, []);
console.log(project);
console.log(project._links.issues);
fetch(project._links.issues).then((res) => console.log(res));
console.log(project); gives me {} and after some time it prints the object, that's why when I try to use project._links.issues it is undefined as I think it isn't resolved yet but I don't know how to make it work.
I solved it by fetching the data in the useEffect hook and saving the response of the api in the state so that I can access it later in my code, like that
const [issues, setIssues] = useState<any>([]);
Promise.all(projectsPromises).then((data) => {
const celoProject: any = data.find((element) => element.id === 338);
setProject(celoProject);
const projectIssues = fetch(celoProject._links.issues)
.then((res) => res.json())
.then((allIssues) => {
setIssues(allIssues);
});
});
If someone has a better way or an explanation why I couldn't access it outside the useEffect, please tell me.
Anything inside the useEffect hook will only execute when the page first loads (because you provided an empty array as the second argument). Anything outside of it will execute on every render (every time props or state changes). That is why it logs {} the first time because the effect is asynchronous and hasn't completed before the component is rendered.
You should run the second fetch in the useEffect hook after the first API request completes. Need more information to determine what exactly is happening beyond this.
const [project, setProject] = useState<any>({});
const api = new Gitlab({
host: "https://example.com",
token: "my token",
});
useEffect(() => {
(async () => {
const projectsPromises = await api.Projects.all().then((allprojects) => {
return allprojects;
});
Promise.all(projectsPromises).then((data) => {
const projectResponse = data.find((element) => element.id === 338)
setProject(projectResponse)
fetch(projectResponse._links.issues).then((res) => {
console.log(res)
// Do something with this response
});
});
})();
return () => {};
}, []);
console.log(project);
console.log(project._links.issues);
I am using a useEffect to get information from firebase and set my redux state thereafter. When I open the page for the first time, all my components contain the correct information. As soon as I refresh the page, all the information is set to nothing? I think it is because the useEffect does not execute again for some reason. Here is my code below:
useEffect(async () => {
setLoading(true);
const fetchData = async () => {
await getConfigs().then((response) => {
const obj = response;
setRedux(obj[0]);
});
};
fetchData();
}, []);
I think the problem is that you provide an async function as a callback to useEffect, which is not allowed. Just get rid of it, like so:
useEffect(() => {
setLoading(true);
const fetchData = async () => {
// Also, you either await or use .then(), not both
const response = await getConfigs();
const obj = response;
setRedux(obj[0]);
};
fetchData();
}, []);
I'm trying to update state immediately after data comes in from the API. The data is coming in, I can see it using the console.log right below my API request. All of the data is right but for some reason, setState never sets in my hook. It just returns and empty array even after the console displays data.
const [experienceData, setExperienceData] = useState([]);
const { match = {} } = props;
useEffect(() => {
async function fetchData() {
if (Object.keys(match.params).length > 0) {
const response = await ApiService.getExperiences(match.params.experieneId);
console.log(response)
setExperienceData(response)
}
}
fetchData();
}, []);
I must be doing something wrong but I can't figure out what that is. Hoping someone on here has run into the same issue.
UPDATE: I just changed everything over the a class and duplicated the exact code on another file and ran into the exact same issue. The console updates with the data, but the setState on the line immediately after the data does not setState.
async componentDidMount() {
if (Object.keys(this.props.match.params).length > 0) {
const response = await ApiService.getExperiences(this.props.match.params.experieneId);
console.log(response[0])
this.setState({ experienceData: response[0], occurrenceData: response[0].occurrences });
}
}
You have to useSetState in a proper way, the issue is in the setExperienceData
const [experienceData, setExperienceData] = useState({response:""});
const { match = {} } = props;
useEffect(() => {
async function fetchData() {
if (Object.keys(props.match.params).length > 0) {
const response = await ApiService.getExperiences(match.params.experieneId);
console.log(response)
setExperienceData(experienceData => ({ ...experienceData, response: response }));
}
}
fetchData();
}, []);
return(<div>check {experienceData.response}</div>)
I see you left the dependency array empty. This tells React to run this effect only once: when the component first renders. If you want your useEffect to respect your state hook, put setExperienceData inside the dependency array
const [experienceData, setExperienceData] = useState([]);
const { match = {} } = props;
useEffect(() => {
fetchData();
}, [props.match.params]);
const async fetchData = () => {
if (Object.keys(match.params).length > 0) {
const response = await ApiService.getExperiences(match.params.experieneId);
console.log(response)
setExperienceData([...response])
}
}
Could you please try passing [match.params] as the second argument to your useEffect.
I am trying to fetch my blobs with axios inside my React app using the Azure REST API (and parse it to JSON as it comes in as a XML response). Problem here is that it fetches correctly once, and when the page is refreshed it does not fetch anything else, showing undefined whenever I try to access any of the data, and returning empty array in console... what am I doing wrong?
const [images, setImgs] = useState([])
useEffect(() => {
const fetchData = async () => {
const response = await axios.get(`https://${process.env.AZURE_SPACE}.blob.core.windows.net/${process.env.AZURE_CONTAINER}?restype=container&comp=list&${process.env.AZURE_TOKEN}`);
const newJson = JSON.parse(convert.xml2json(response.data, {compact: true, spaces: 4}))
setImgs(newJson);
}
fetchData();
console.log(images)
}, []);
Try
await fetchData();
Otherwise, your console log is called before the answer coming back from azure
So, if you checking console.log(images) why this is still blank :
setImgs(newJson); // is also async
fetchData();
console.log(images) //<-- So it won't reflected immediately right after fetchData()
But your DOM will get updated, you can confirm it.
You can run the below snippet and check HTML and conosle.log both :
setUsers([...users, "Vivan" , "Darshita"]); // is async
console.log(users); // Due to setUsers's async behaviour it still console.log old values
const { useState , useEffect } = React;
const App = () => {
const [users,setUsers] = useState(['Vivek' , 'Darsh']);
useEffect(() => {
setTimeout(() => {
setUsers([...users, "Vivan" , "Darshita"]);
console.log(users);
},2000);
},[]);
return (
<div>
{ users.map(user => <p>{user}</p>) }
</div>
);
}
ReactDOM.render(<App />, document.getElementById('react-root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react-root"></div>
So it sounds like two separate questions.
How to solve the await issue:
const [images, setImgs] = useState([])
useEffect(() => {
const wrapperFunc = async () => {
const fetchData = async () => {
const response = await axios.get(`https://${process.env.AZURE_SPACE}.blob.core.windows.net/${process.env.AZURE_CONTAINER}?restype=container&comp=list&${process.env.AZURE_TOKEN}`);
const newJson = JSON.parse(convert.xml2json(response.data, {compact: true, spaces: 4}))
setImgs(newJson);
}
await fetchData();
console.log(images)
};
wrapperFunc();
}, []);
The code inside the wrapperFunc can now wait for fetchData to return before writing to the console.
The second issue where it is only getting called once. It could be fixed as a result of this new code. However, I ran into something similar with React Hot Loading where the gating state was already set, so it would rerun my new code. I had to just change the state manually and then the code ran.