function App() {
const [todos, setTodos] = useState(null);
useEffect(() => {
const GetTodos = async () => {
try {
const { data } = await axios.get("api/orders");
console.log(data);
setTodos(data);
console.log(todos);
} catch (err) {
console.log(err);
}
};
GetTodos();
}, []);
return (
<div className="App">
<h1>hello</h1>
{todos?.map((todo) => (
<p key={todo.ID}>{todo.ID}</p>
))}
</div>
);
}
How can I make the data I got from the API display on the page, I can see that it works when I log it to the console but it doesn't show up on the page
Okay the problem is your data returns an Array of Arrays.
Because your data has just one array nested inside, we can just use it as the data hook, something like this:
setTodos(data[0]);
to understand, here is an example
You could do as below, calling setTodos(data[0]) in your try-catch, as your API seems to be returning an array with the data you want at position 0.
function App() {
const [todos, setTodos] = useState(null);
useEffect(() => {
const GetTodos = async () => {
try {
const { data } = await axios.get("api/orders");
console.log(data);
setTodos(data[0]);
} catch (err) {
console.log(err);
}
};
GetTodos();
}, []);
return (
<div className="App">
<h1>hello</h1>
{todos && todos.map((todo) => (
<p key={todo.ID}>{todo.ID}</p>
))}
</div>
);
}
Related
i have my json received from api call and is saved in the state "data"
i want to show a loading screen while api is being fetched like i have a state for that too "Loading"
Loading ? Then render data on elements : Loading..
const App = () => {
const [data, setData] = useState([]);
const [Loading, setLoading] = useState(false);
useEffect(() => {
Fetchapi();
}, []);
const Fetchapi = async () => {
try {
await axios.get("http://localhost:8081/api").then((response) => {
const allData = response.data;
setData(allData);
});
setLoading(true);
} catch (e) {
console.log(e);
}
};
return (
<div>
i need my json object rendered here i tried map method on data and i am
getting errors and i have my json2ts interfaces imported in this
</div>
);
};
export default App;
I would camelCase your values/functions and move your fetchApi into the effect itself, as currently its a dependency.
Put setLoading(true) above your fetch request as currently it's not activating until the fetch goes through.
Then below it put setLoading(false), and also inside of your catch.
In your return statement you can now add something like this:
<div>
{loading ? "Loading..." : JSON.stringify(data)}
</div>
Edit
Example for the commented requests.
import { Clan } from "../clan.jsx"
// App
<div>
{loading ? "Loading..." : <Clan data={data}/>}
</div>
// New file clan.jsx
export const Clan = (props) => {
return (
<div>
<h1>{props.data.clan.name}</h1>
</div>
);
}
try this
interface ResponseData {
id: string
// other data ...
}
const App = () => {
const [data, setData] = useState<ResponseData | null>(null)
const [Loading, setLoading] = useState(true)
useEffect(() => {
Fetchapi()
}, [])
const Fetchapi = async () => {
try {
setLoading(true) // USE BEFORE FETCH
await axios.get("http://localhost:8081/api").then(response => {
setLoading(false) // SET LOADING FALSE AFTER GETTING DATA
const allData: ResponseData = response.data
setData(allData)
})
} catch (e) {
setLoading(false) // ALSO SET LOADING FALSE IF ERROR
console.log(e)
}
}
if (Loading) return <p>Loading...</p>
if (data?.length)
return (
<div>
{data.map(d => (
<div key={d.id}>{d.id}</div>
))}
</div>
)
return <div>no data found</div>
}
export default App
I am using the following code for fetching and passing data from firestore.
there are four data in my firestore collection. I am able to fetch all four of them, (i checked this on console), but in NewRecipe component only the first data is getting passed as props. not sure why the other three data not getting passed as props.
this is component where i am fetching data :
const Home = () => {
const [data, setData] = useState(null);
const [isPending, setIsPending] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
setIsPending(true);
projectFirestore
.collection("recipes")
.get()
.then((snapshot) => {
if (snapshot.empty) {
setError("No recipes");
setIsPending(false);
} else {
let result = [];
snapshot.docs.forEach((doc) => {
result.push({ id: doc.id, ...doc.data() });
setData(result);
setIsPending(false);
});
}
})
.catch((e) => {
setError(e);
});
}, []);
console.log("data", data);
return (
<div>
{error && <div className="errors">{error}</div>}
{isPending && <div className="Loading">Loading.......</div>}
{data && <NewRecipe data={data} />}
</div>
);
};
export default Home;
this is NewRecipe component where I am receiving props
const NewRecipe = ({data}) => {
console.log("data new recipe", data)
return (
<div className='recipe_list'>
{data.map((item)=>{
return (
<div key={item.id} className='card'>
<h3>{item.title}</h3>
<p>it takes around {item.cookingTime}</p>
<p>{item.method.substring(0,100)}</p>
<Link to={`/recipes/ ${item.id}`}className='btn'> Read more</Link>
</div>
)})}
</div>
)
}
Try to place setPending(false) outside (just after) the forEach block.
I am trying to call a component that shows the details of a notification when the notification is clicked. However, I kept on getting an error of too many re-renders.
This is my Notifications code
This component calls the database to get the list of notifications and then sets the first notification as the default notification clicked.
const Notification = (hospital) => {
const [users, setUsers] = useState([]);
const [search, setSearch] = useState(null);
const [status, setStatus] = useState(null);
const [notifDetails, setNotification] = useState();
useEffect(async () => {
await axios
.get("/notifications")
.then((res) => {
const result = res.data;
setUsers(result);
setNotification(result[0]);
})
.catch((err) => {
console.error(err);
});
}, []);
return(
<div className="hospital-notif-container">
{filteredList(users, status, search).map((details, index) => {
for (var i = 0; i < details.receiver.length; i++) {
if (
(details.receiver[i].id === hospital.PK ||
details.receiver[i].id === "others") &&
details.sender.id !== hospital.PK
) {
return (
<div
className="hospital-notif-row"
key={index}
onClick={() => setNotification(details)}
>
<div className="hospital-notif-row">
{details.name}
</div>
</div>
);
}
}
return null;
})}
</div>
<NotificationDetails details={notifDetails} />
);
}
For NotificationDetails:
This function is triggered when a notification is clicked from Notifications. The error is said to be coming from this component.
const NotificationDetails = ({ details }) => {
const [loading, setLoading] = useState(true);
useEffect(() => {
if (Object.keys(details).length != 0) {
setLoading(false);
}
}, [details]);
if (!loading) {
return (
<>
<div className="hospital-details-container">
<h2>{details.sender.name}</h2>
</div>
</>
);
} else {return (<div>Loading</div>);}
};
What should I do to limit the re-render? Should I change the second argument of the useEffects call? Or am I missing something in my component?
I tried calling console.log from NotificationDetails and it shows that it is infinitely rendering with the data I set in axios which is result[0]. How is this happening?
Your problem should be in NotificationDetails rendering. You should write something like:
const NotificationDetails = ({ details }) => {
const [loading, setLoading] = useState(true);
useEffect(() => {
if (details.length != 0) {
setLoading(false);
}
}, [details]);
return (
<div>
{loading &&
<div className="hospital-details-container">
<div className="hospital-details-header">
<h2>{details.sender.name}</h2>
</div>
</div>
}
{!loading &&
<div>
<ReactBootStrap.Spinner animation="border" />
</div>
}
</div>
);
}
With return outside the condition statement.
EDIT
Now I noted that you have an async useEffect that is an antipattern. You should modify your useEffect in this way:
useEffect(() => {
(async () => {
await axios
.get("/notifications")
.then((res) => {
const result = res.data;
setUsers(result);
setNotification(result[0]);
})
.catch((err) => {
console.error(err);
});
})()
}, []);
I'm working with tmdb api, I've been using react's useEffect and useContext for minor stuff and it works. I decided to use the api and it has been going into this infinite loop anytime I try to run it. I'm using axios with useEffects and useContext. Below is the component calling axios
enter image description here
function MovieList(props) {
useEffect(() => {
const getMovies = async () => { };
try {
const response = await axios.get(movieUrl, { cancelToken: source.token });
addMovies(response.data.results);
// setLoading(false)
} catch (error) {
if (axios.isCancel(error)) {
console.log('Request canceled', error.message);
} else {
// handle error
throw error
}
}
getMovies();
}, []);
return (
<React.Fragment>
<div className="container-fluid pl-5">
<h2 className="white mt-4">{pageTitle}</h2>
<div className="row">
{movies.map((movie) => {
return <Movie key={movie.id} movie={movie} />;
})}
</div>
</div>
</React.Fragment>
);
}
My code goes into an infinite loop and it's driving me crazy.
And my context code is found below:
export const MovieProvider = (props) => {
const [isFav, setIsFav] = useState(false)
const [movies, setMovies] = useState([]);
const [filtered, setFilteredMovies] = useState([])
const addMovies = (res) => {
setMovies([...res]);
}
const addFavMovies = (res) => {
if(res){
setMovies([...res]);
}
}
const addFilteredMovies = (res) => {
setFilteredMovies([...filtered, res]);
}
return (
<MovieContext.Provider value={{
fav: [isFav, setIsFav],
movies, addMovies, addFavMovies,
filtered, addFilteredMovies,
}}>
{props.children}
</MovieContext.Provider>
)
}
Having done the necessary to read the data using fetchAPI, I am having problems displaying the content because of the nature of the array.
import React, { useState, useEffect } from "react";
function Home() {
const [userData, setUserData] = useState([]);
async function getData() {
let response = await fetch("https://api.xxxxxxxx.io/something/students");
let data = await response.json();
return data;
}
//call getData function
getData().then((data) => console.log(data)); //
useEffect(() => {
getData()
.then((data) => {
setUserData(data);
})
.catch((error) => {
console.log(error);
});
}, []);
return (
<div>
{Object.keys(userData).map((item, index) => (
<div key={index}>{item}</div>
))}
</div>
);
}
export default Home;
When I checked the console, the data are displayed but it is only showing students with no other data displayed.
I have the data below.
Try the following changes:
const [userData, setUserData] = useState({ students: [] });
...
return (
<div>
{userData.students.map((item, index) => (
<div key={index}>{item}</div>
))}
</div>
);