Wykorzystanie statusu żądania w Redux

Na poprzednich zajęciach za pomocą dodatkowych reducerów opisaliśmy, co ma zrobić nasza aplikacja, jeśli fetchProducts wysyła podczas żądania akcje pending, fulfilled i rejected. Teraz możemy pokazać użytkownikowi, na jakim etapie aktualnie znajduje się ładowanie danych.

Otwórzmy naszą aplikację z produktami, a w niej plik ProductsList.jsx. Pierwsze, co zrobimy, to utworzymy osobny komponent dla karty produktu ProductCard. Zrobimy to zaraz po linijkach importów przed funkcją ProductsList. Jako props przekażemy mu product:

products/ProductsList.jsxconst ProductCard = ({ product }) => {
  return ()
}

A teraz w puste okrągłe nawiasy return przenieśmy cały kod do wyświetlania danych produktu z dispProducts:

products/ProductsList.jsxconst ProductCard = ({ product }) => {
  return (
    <div key={product.id} className="product-excerpt">
      <h3>{product.name}</h3>
      <SellerOfProd sellerId={product.seller} />
      <p>{product.desc.substring(0, 100)}</p>
      <UserReactions product={product} />
      <Link to={`/products/${product.id}`} className="link-btn">
        view
      </Link>
    </div>
  )
}

I usuniemy w ProductsList pozostałą linię kodu. Nie jest nam już potrzebna:

products/ProductsList.jsxconst dispProducts = products.map((product) => ())

A teraz na początku kodu funkcji ProductsList utwórzmy jeszcze parę zmiennych, error i content. Pierwsza będzie dla błędu, do drugiej będziemy zapisywać to lub inne zawartość w zależności od statusu żądania. Zróbmy to przed const dataFetch = useRef(false):

products/ProductsList.jsxconst error = useSelector((state) => state.products.error)
let content

Teraz przed komendą return komponentu ProductsList napiszmy blok kodu z warunkami, przy których w content będzie zapisywana ta lub inna zawartość w zależności od statusu. Pierwszy opiszemy status 'in progress' - gdy nasze żądanie zostało wysłane. W tym przypadku poinformujemy użytkownika, że trwa ładowanie danych:

products/ProductsList.jsxif (productStatus === 'in progress') {
  content = <p>Products list loading ...</p>
}

Jeśli nasze ładowanie przebiegło pomyślnie (oznaczaliśmy to jako 'success'), to musimy wyświetlić listę otrzymanych produktów. Wyświetlimy ją w map przy pomocy komponentu ProductCard, któremu propsem przekażemy product:

products/ProductsList.jsxif (productStatus === 'in progress') {
  content = <p>Products list loading ...</p>
} else if (productStatus === 'success') {
  content = products.map((product) => (
    <ProductCard key={product.id} product={product} />
  ))
}

I ostatni status, który mamy - to 'fail'. Dodajmy i jego. Wykorzystajmy tutaj zmienną error, do której wyżej zapisaliśmy błąd ze stanu:

products/ProductsList.jsxif (productStatus === 'in progress') {
  content = <p>Products list loading ...</p>
} else if (productStatus === 'success') {
  content = products.map((product) => (
    <ProductCard key={product.id} product={product} />
  ))
} else if (productStatus === 'fail') {
  content = <div>{error}</div>
}

I ostatnim krokiem w bloku kodu dla return zamienimy stary {dispProducts} na {content}.

Uruchommy naszą aplikację, kliknijmy w menu 'Products'. Wszystko działa. Widzimy, że około 2 sekund (tak jak ustawiliśmy na serwerze) pod formularzem dodania produktu wisi napis 'Products list loading ...', a potem pojawia się lista produktów.

Задание 1

Otwórz twoją aplikację ze studentami. Otwórz w niej plik StudentsList.jsx. Utwórz w nim nowy komponent StudentCard. Przenieś do niego kod z dispStudents, jak pokazano na lekcji.

Задание 2

Utwórz w funkcji StudentsList zmienne error i content. Przypisz zmiennej content zawartość w zależności od statusu żądania. Nie zapomnij zamienić w zwracanym kodzie HTML starego dispStudents na content.