skip to Main Content

So I’m fetching some data and this data returns an array and I want to map this array, the problem is that the fetch default value is an empty object, I can change the default value of the fetch but that still doesn’t work and I can’t seem to find an answer that fixes my code.

Here is my code

import { useState, useRef, useMemo, createRef, useEffect } from "react";
import { Button } from "react-bootstrap";
import TinderCard from "react-tinder-card";
import { AnimalCard } from "../AnimalCard";
import { useFetch } from "../../../hooks/useFetch";

import "./index.css";

export const AnimalStack = () => {
  const { loading, error, data } = useFetch("animal-adp/"); // returns {} by default

  const [animals, setAnimals] = useState([]);
  
  useEffect(()=> {
    if (Array.isArray(data)) {
      setAnimals([...data])
    }
  },[])
 // here is some more code that i'm not showing because its irrelevant

 
  return (
    <>
      <div
        className="d-flex justify-content-center w-100"
        style={{ height: "80vh" }}
      >
        {Array.isArray(animals) ?
          animals.map((animal, index) => (
            
            <TinderCard
              className="animal-card"
              ref={childRefs[index]}
              key={animal.id}
              onSwipe={(dir) => swiped(dir, animal.name, index)}
              onCardLeftScreen={() => outOfFrame(animal.name, index)}
            >
              <AnimalCard character={animal} />
            </TinderCard>
          ))
         : (
          <div>Cargando ...</div>
        )}
      </div>
      <div className="m-2 p-1 rounded-2 w-100 d-flex flex-wrap flex-shrink-0 justify-content-center align-items-center gap-2">
        <Button onClick={() => swipe("left")}>Izquierda</Button>
        <Button onClick={() => swipe("right")}>Derecha</Button>
      </div>
    </>
  );
}

If you need to see any more parts of the code to undestand the error just tell me and I will edit this question

I already tried changing the default response value to an empty array, I’ve tried not using an useEffect hook -> this results in an infinite loop and I’ve tried basically everything that I found here.

2

Answers


  1. There’s no need to maintain a copy of the data in the animals state; the useFetch hook already provides the data as reactive state.

    Your issue is that you never update animals because your effect hook runs only once on mount when data is (probably) undefined.

    Simply use the data from your hook. You can even rename it to animals if it helps

    const { loading, error, data: animals } = useFetch("animal-adp/");
    
    if (loading) {
      return <p>Loading...</p>;
    }
    
    if (error) {
      return <p className="error">{error}</p>;
    }
    
    return (
      <>
        <div
          className="d-flex justify-content-center w-100"
          style={{ height: "80vh" }}
        >
          {animals?.map((animal, index) => (
            <TinderCard
              className="animal-card"
              ref={childRefs[index]}
              key={animal.id}
              onSwipe={(dir) => swiped(dir, animal.name, index)}
              onCardLeftScreen={() => outOfFrame(animal.name, index)}
            >
              <AnimalCard character={animal} />
            </TinderCard>
          ))}
        </div>
        <div className="m-2 p-1 rounded-2 w-100 d-flex flex-wrap flex-shrink-0 justify-content-center align-items-center gap-2">
          <Button onClick={() => swipe("left")}>Izquierda</Button>
          <Button onClick={() => swipe("right")}>Derecha</Button>
        </div>
      </>
    );
    

    I’m assuming your useFetch hook looks something like this…

    const fetchWrapper = async (url) => {
      const res = await fetch(url);
      if (!res.ok) {
        throw new Error(`Fetch failed for ${url}`);
      }
      return res.json();
    };
    
    const useFetch = (url) => {
      const [data, setData] = useState();
      const [loading, setLoading] = useState(true);
      const [error, setError] = useState();
    
      fetchWrapper(url)
        .then(setData)
        .catch(setError)
        .finally(() => setLoading(false));
    
      return { data, error, loading };
    };
    
    export { useFetch };
    
    Login or Signup to reply.
  2. the problem is in your useEffect , you must add dependency in useEffect,like this,
    useEffect(()=> { if (data. length > 0) { setAnimals([...data]) } },[data])

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search