Wywołanie funkcji w useEffect

0

Mam pewien problem jak wpakować funkcję combineItems po tym dopiero jak będzie wywołana funkcja getItems ta w useEffect. Test jest tablicą obiektów dla przykładu jeden :
screenshot-20210612135524.png
i do momentu odświeżenia strony normalnie mogę się dostać do item.image
screenshot-20210612135616.png
jednak po odświeżeniu strony dostaje błąd
screenshot-20210612135700.png
Może źle się za to zabieram i jest inna droga do uzyskania efektu ?

import { Fragment, useState, useEffect } from "react";

const ItemList = (props) => {
  const [items, setItems] = useState([]);
  const urlItems =
    "https://ddragon.leagueoflegends.com/cdn/11.12.1/data/en_US/item.json";
  useEffect(() => {
    const getItems = async () => {
      const response = await fetch(urlItems);
      const data = await response.json();
      const items = Object.values(data.data).map(
        ({
          name,
          plaintext,
          tags,
          image,
          gold,
          requiredAlly,
          depth,
          into,
          description,
        }) => ({
          name,
          plaintext,
          tags: tags,
          image: image.full,
          gold: gold.total,
          requiredAlly,
          depth,
          into,
          description,
        })
      );
      setItems(items);
    };
    getItems();
  }, []);

  const sample = (arr) => arr[Math.floor(Math.random() * arr.length)];

  const shuffleArray = (array) => {
    for (let i = array.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [array[i], array[j]] = [array[j], array[i]];
    }
    return array;
  };

  const mythicItems = items.filter((item) => {
    return (
      item.gold > 2000 &&
      item.gold < 5000 &&
      item.into !== undefined &&
      item.requiredAlly === undefined
    );
  });

  const boots = items.filter((item) => {
    return (
      item.plaintext.includes("Movement Speed") &&
      item.into === undefined &&
      item.depth === 2
    );
  });

  const supportItems = items.filter((item) => {
    return item.description.includes("Quest:");
  });

  const normalItems = items.filter((item) => {
    return item.depth === 3 && item.into === undefined;
  });

  const random = () => {
    const randomItems = [];
    randomItems.push(sample(mythicItems));
    randomItems.push(sample(boots));
    if (props.filteredSupport) {
      randomItems.push(sample(supportItems));
    }
    return randomItems;
  };

  const combineItems = () => {
    const shuffledNormalItems = shuffleArray(normalItems);
    const finalItems = [];
    finalItems.push(...random());
    finalItems.push(...normalItems);
    finalItems.push(...shuffledNormalItems);
    const finalItemsSliced = finalItems.slice(0, 6);
    return finalItemsSliced;
  };
  const test = combineItems();
  console.log(test);
  test.map((item) => console.log(item.image));
  return (
    <Fragment>
      {test.map((item) => {
        return (
          <img
            key={item.image}
            src={`http://ddragon.leagueoflegends.com/cdn/11.12.1/img/item/${item.image}`}
            alt={`item-${item.name}`}
          ></img>
        );
      })}
    </Fragment>
  );
};

export default ItemList;
0

Odwołujesz się do pola obiektu ... w pustej tablicy.
Kod wykonuje się zanim w tablicy masz oczekiwane elementy, cały stacktrace masz na załączonym zdjęciu.

0

@urke: Ok to w jaki sposób mogę się odwołać do tej tablicy "test" dopiero jak uzupełnię.

1

@Raloseq Funckja sample() u Ciebie ma zwrócić losowy item, ale czasem masz pusty array więc funkcja zwraca undefined.

Po prostu nie wołaj funkcji sample(), jeśli array jest jeszcze pusty

0

@TomRiddle: Wow dzięki ile ja się nad tym nasiedziałem. Sam bym tego nie wykminił :D takie sprawdzenie zrobiłem

 const random = () => {
   const randomItems = [];
   if (mythicItems.length > 0) {
     randomItems.push(sample(mythicItems));
   }
   if (boots.length > 0) {
     randomItems.push(sample(boots));
   }

   if (props.filteredSupport && supportItems.length > 0) {
     randomItems.push(sample(supportItems));
   }
   return randomItems;
 };
1

Piszesz strasznie dużo niepotrzebnego kodu. Ta Twoja funkcja

  const combineItems = () => {
    const shuffledNormalItems = shuffleArray(normalItems);
    const finalItems = [];
    finalItems.push(...random());
    finalItems.push(...normalItems);
    finalItems.push(...shuffledNormalItems);
    const finalItemsSliced = finalItems.slice(0, 6);
    return finalItemsSliced;
  };

można ją zapisać tak:

const combineItems = () => [...random(), ...normalItems, ...shuffleArray(normalItems)].slice(0, 6);

I wyjdzie na to samo, tylko 100x bardziej czytelnie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1