Приложение "Звёздные войны". Ч1.


Продолжение курса Юрия Бура React + Redux - Профессиональная Разработка. Часть 6.

Создаём пустой проект

$ npx create-react-app star-db

Идём на сайт https://bootswatch.com/ выбираем там тему darkly для будущего проекта. Нажимаем под темой кнопку download, скачивается файл bootstrap.min.css

Подключаем его в файл index.html в папке public

Информацию для отображения в приложении мы будем получать от API https://swapi.co/

Для получения данных могут использоваться
XML Http Request - используется 20 лет, немного устарел
Fetch API

Кроме того, есть еще несколько библиотек, которые умеют работать с сервером тоже и используются если создаётся не только фронтенд, а полное full стек приложение и одного только браузерного API будет недостаточно

Получим данные про Люка Скайуокера, персону номер один во вселенной звёздных войн

function getData() { 
  const url = 'https://swapi.co/api/people/1/';
  fetch(url)
    .then(res => res.json())
    .then(data => { 
      console.log(data);
    });
}
getData()

Перепишем этот же код. используя acync/await

async function getData() { 
  const url = link;
  const res = await fetch(url);
  const data = await res.json();
  console.log(data);
}
getData() 

Кроме json() существуют другие функции для других типов ответа arrayBuffer(), blob(), text(), formData().

Обработка ошибок


Перепишем функцию getData так, чтобы она возвращала не только результат, но и ошибки

async function getData(url) { 
  const res = await fetch(url);
  const data = await res.json();
  return data;
}

getData('https://swapi.co/api/people/1/')
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log(err);
  })

Такой код обработает ошибки подключения к интернету. Но если ошибку возвратит сервер, такие ошибки нужно отлавливать выше, в самом res

async function getData(url) { 
  const res = await fetch(url);
    if(!res.ok) {
      throw new Error(res.status)
    }
  const data = await res.json();
  return data;
}

getData('https://swapi.co/api/people/14444')
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log(err);
  })
// Error: 404

Для работы с API создаём отдельную папку src\services и в ней файл swapi-service.js. Для остального приложения этот файл будет просто источником данных

Пишем код


export default class SwapiService {

  _apiBase = 'https://swapi.co/api';

  async getResource(url) {
    const res = await fetch(`${this._apiBase}${url}`);

    if (!res.ok) {
      throw new Error(`Could not fetch ${url}` +
        `, received ${res.status}`)
    }
    return await res.json();
  }

  async getAllPeople() {
    const res = await this.getResource(`/people/`);
    return res.results;
  }

  getPerson(id) {
    return this.getResource(`/people/${id}/`);
  }
}
const swapi = new SwapiService();
swapi.getAllPeople().then((data) => {
  console.log(data)
})

Получаем результат - объект из 10 персонажей
Но по ссылке https://swapi.co/api/people/ персонажей 87

Получить персонажей по id позволяет метод getPerson

swapi.getPerson(44).then((data) => {
  console.log(data.name)
})
// Darth Maul

По такому же принципу получаем информацию о планетах и кораблях.

Выводы
- код, который работает с сетью, лучше изолировать в отдельный класс
- компонентам не нужно знать откуда они получают данные
- такой подход упростит отладку и тестирование кода