Reputation: 665
I'm a complete beginner in react and I am fetching data from https://www.boredapi.com/documentation#endpoints-price . With http://www.boredapi.com/api/activity/
you get a random activity object in the format of
{
"activity": "Learn Express.js",
"accessibility": 0.25,
"type": "education",
"participants": 1,
"price": 0.1,
"link": "https://expressjs.com/",
"key": "3943506"
}
I'm trying to fetch 10 of these objects using react hooks and then display them . However with my code below when I try to fetch and display a single activity name nothing happens . I initialize an array with hooks and I want to append a new object each time I fetch
useFetch.js to fetch an activity
import {useState , useEffect} from 'react';
export default function useFetch(){
const [activities,setActivities] = useState([]);
const getActivities = async () =>{
for(let k=0;k<10;k++){
let response = await fetch("http://www.boredapi.com/api/activity/");
let result = await response.json();
setActivities((oldstate)=>[...oldstate,result])
}
}
useEffect(()=>{
getActivities();
}, [])
return {activities};
}
AcitivityBar.js to display activities
import React from 'react';
import useFetch from './useFetch';
export default function ActivityBar(){
const {activities} = useFetch();
console.log(activities)
return (
<div className="activities-container">
{
(activities.map((a , index)=>{
return <h1 key = {index}>hi</h1>
}))
}
</div>
);
}
Upvotes: 1
Views: 374
Reputation: 1984
You could use Promise.all
to wait for multiple requests in parallel:
This will show results simultaneously not one after one.
import { useState, useEffect } from 'react'
export default function useFetch() {
const [activities, setActivities] = useState([])
const getActivities = async () => {
let arr = []
for (let k = 0; k < 10; k++) {
arr[k] = new Promise(async (resolve, reject) => {
fetch('http://www.boredapi.com/api/activity/').then((response) => {
resolve(response.json())
})
})
}
Promise.all(arr).then((results) => {
setActivities(results)
})
}
useEffect(() => {
getActivities()
}, [])
return { activities, getActivities }
}
Upvotes: 1
Reputation: 2614
Make sure you append new activities properly from the response using spread operator, like this:
let response = await fetch("http://www.boredapi.com/api/activity/");
let activity = await response.json();
setActivities(prev => [...prev, activity]);
EDIT:
The main issue is with the scoping, the activities
is not persisted across render. You should consider using prev value.
Upvotes: 1
Reputation: 267
You should probably change your iteration to something like this:
const getActivities = async () =>{
for(let k=0;k<10;k++){
let response = await fetch("http://www.boredapi.com/api/activity/");
let result = await response.json();
setActivities(prev => [...prev, result])
}
}
the useState also has a function input that returns the actual value. You shouldn't rely on the activities since that is always an empty array when all the items get loaded at once
Upvotes: 1