Применение статуса запроса в Redux

На прошлых занятиях мы с помощью дополнительных редьюсеров описали, что делать нашему приложению, если fetchProducts отправляет при запросе экшены pending, fulfilled и rejected. Теперь мы можем показать пользователю на какой стадии сейчас загрузка данных.

Давайте откроем наше приложение с продуктами, а в нем файл ProductsList.jsx. Первое, что мы сделаем, это создадим отдельный компонент для карточки продукта ProductCard. Сделаем это сразу после строчек импорта перед функцией ProductsList. В качестве пропса передадим ему product:

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

А теперь в пустые круглые скобочки return перенесем весь код для отображения данных продукта из 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>
  )
}

И уберем в ProductsList оставшуюся строчку кода. Она нам больше не нужна:

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

А теперь в начале кода функции ProductsList заведем еще пару переменных, error и content. Первая у нас будет для ошибки, во вторую мы будем записывать то или иное содержимое в зависимости от статуса запроса. Сделаем это перед const dataFetch = useRef(false):

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

Теперь перед командой return компонента ProductsList напишем блок кода с условиями, при которых в content будет заноситься то или иное содержимое в зависимости от статуса. Первым мы опишем статус 'in progress' - когда наш запрос отправлен. В этом случаем мы сообщим пользователю, что идет загрузка данных:

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

Если наша загрузка прошла успешно (мы обозначали это как 'success'), то нам нужно вывести список полученных продуктов. Выведем его в map при помощи компонента ProductCard, которому пропсом передадим 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} />
  ))
}

И последний статус, который у нас имеется - это 'fail'. Добавим и его. Используем здесь переменную error, в которую мы выше записали ошибку из стейта:

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

И последним шагом мы в блоке кода для return заменим старый {dispProducts} на {content}.

Запустим наше приложение, кликнем в меню по 'Products'. Все работает. Видим, что примерно 2 секунды (как мы и установили на сервере) у нас под формой добавления продукта висит надпись 'Products list loading ...', а потом появляется список продуктов.

Задание 1

Откройте ваше приложение со студентами. Откройте в нем файл StudentsList.jsx. Создайте в нем новый компонент StudentCard. Перенесите в него код из dispStudents, как показано в уроке.

Задание 2

Создайте в функции StudentsList переменные error и content. Присвойте переменной content содержимое в зависимости от статуса запроса. Не забудьте заменить в возвращаемой верстке старый dispStudents на content.