1

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

3 Answers 3

1

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 }
}
Sign up to request clarification or add additional context in comments.

2 Comments

so promises show results simultaneously and async await one after the other ?
It fetches one after one. In other words, the next fetching will be triggered after prev fetching completed.
1

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

Comments

1

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.

10 Comments

I changed that later . But what about the iteration ?
which iterations?
To display the names
Are you getting the activities, can you log that?
I try to but I get undefined
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.