How do I set state using useState inside the useEffect method? - reactjs

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>
)
}))

Related

React JS. Trying to display data from a local JSON file

I am quite new in learning React and now I am trying to implement some dynamic filters on a locat data set and I am stuck at displaying data from my local file.
Data entries look like this:
I was trying to use the fetch() API but for some reason the data is not displayed on the page. Most probably I am not reffering correct to the right attributes.
`
import data from '../file2.json'
import React, { useEffect, useState } from "react";
const Planner = () => {
const [user, setUser] = useState([]);
const fetchData = () => {
return fetch(data)
.then((response) => response.json())
.then((data) => setUser(data));
}
useEffect(() => {
fetchData();
},[])
return (<main>
<h1>Restaurant List</h1>
<ul>
{user && user.length > 0 && user.map((userObj, index) => (
<li key={userObj.restaurant.R.res_id}>{userObj.name}</li>
))}
</ul>
</main>
)
};
export default Planner;`

React cant fetch data from API

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.

Axios with random API

I am trying to use random API in my application using axios and I get error that "TypeError: randomData.map is not a function". Maybe someone could tell me what I'm doing wrong?
import './App.css';
import {useEffect, useState} from "react";
import axios from 'axios';
function App() {
const [randomData, setRandomDate] = useState([])
useEffect(() => {
axios.get('https://randomuser.me/api')
.then(res => {
console.log('Getting from: ', res.data)
setRandomDate(res.data)
})
.catch(err => console.log(err))
}, [])
const arr = randomData.map((data, index) => {
return (
<p>{data}</p>
)
})
return (
<div className="App">
<h1>Learning React:</h1>
{arr}
</div>
);
}
export default App;
Your issue is that randomuser api returns an object
{
info: ...,
results: [{}]
}
so when you setRandomData to just res.data, you are assigning an object to your state, and map is not part of an object prototype.
What you need to do is to replace setRandomDate(res.data) with setRandomDate(res.data.results) and now you will be able to map that array.
like
const arr = randomData.map((data, index) => {
return (
<p>{data.email}</p>
)
})

useEffect and Axios getting a null json

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

React Native -Flatlist renderItem promise

I have a working flatlist in react native
<FlatList
data={orders}
keyExtractor={item => item._id}
renderItem={({ item }) => (renderItem(item))}
/>
I've added a new promise withing my renderItem function like :
const renderItem = (item) => {
const getRestaurant = async (id) => {
uri = 'https://xxx.xxx.xxx/api/list/xxx/' + id ;
return fetch(uri)
.then((response) => response.json())
.then((json) => {
return json;
//console.log("json=>"+json[0].name);
})
.catch((error) => {
console.error(error);
});
}
const promise = getRestaurant(item.restaurantId);
promise.then(data =>{
console.log(data[0].name)
return (
<Text>{data[0].name}</Text>
)
})}
If I do a
console.log(data[0].name)
the information i am looking for is correct but i simply cannot return that information in my flatlist to be displayed . Ive done something like :
return (
<Text>{data[0].name}</Text>
)
but nothing is being display on my flatlist !
Can anyone please help me . Thank you
You cannot use the variables directly inside the component , you need to use state.
Because when there is a change in state , react-native will render your components.
For example you can make use of useState hook
first import useState from like below
import React, { useState } from "react";
and then inside ur function
const [response, setResponse] = React.useState(false);
and then inside ur promise
promise.then(data =>{
setResponse(data[0].name)
return (
<Text>{response}</Text>
)
})}

Resources