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


Когда определились с источником данных, выясним, какие компоненты нам понадобятся

Приложение будет выглядеть приблизительно так


Соответственно, нам нужен будет хедер с логотипом и вкладками люди-планеты-корабли, блок "случайная планета" и три похожих блока с описанием людей, планет и кораблей

Получение данных с сервера

Рассмотрим компонент random-planet, который должен получать от сервера данные о планете и раз в несколько секунд обновлять их

Импортируем файл swapi-service.js

import SwapiService from '../../services/swapi-service';

Внутри класса RandomPlanet  инициализируем swapiService

swapiService = new SwapiService();

Создаём стейт

  state = {
    id: null,
    name: null, 
    population: null,
    rotationPeriod: null, 
    diameter: null
  };

Создаём метод updatePlanet(), который будет возвращать данные о планете по её id

updatePlanet() {
    const id = 5;
    this.swapiService
      .getPlanet(id)
      .then(this.onPlanetLoaded);
  }

Внутри него вызываем метод onPlanetLoaded, который обновляет стейт

  onPlanetLoaded = (planet) => {
    this.setState({ 
      id: planet.id,
      name: planet.name, 
      population: planet.population,
      rotationPeriod: planet.rotation_period, 
      diameter: planet.diameter    
    });
  };

Для вызова updatePlanet() используем конструктор

  constructor() {
    super();
    this.updatePlanet();
  }

Сайт https://swapi.co/ не содержит никаких картинок. Зато картинки есть на сайте https://starwars-visualguide.com/
Больше того, последний использует API первого и все картинки имеют те же id, что и swapi.co

Например,
https://starwars-visualguide.com/assets/img/planets/12.jpg

Получить число из строки позволяет регулярное выражение, например, такое

planet.url.match(/\d+/g)

Займёмся рефакторингом кода
Создаём функцию преобразующую ответ API в нужный нам объект в swapi-service.js

  _transformPlanet(planet) {
    return {
      id: planet.url.match(/\d+/g),
      name: planet.name, 
      population: planet.population,
      rotationPeriod: planet.rotation_period, 
      diameter: planet.diameter 
    }

Изменим код getPlanet

  async getPlanet(id) {
    const planet = await this.getResource(`/planets/${id}/`);
    return this._transformPlanet(planet);
  } 

В компоненте random-planet благодаря этому существенно сокращается количество кода, он становится чище проще и понятнее

  state = {
    planet: {}
  };

  onPlanetLoaded = (planet) => {
    this.setState({ planet });
  };

  updatePlanet() {
    const id = Math.floor(Math.random() * 18 + 2);
    this.swapiService
      .getPlanet(id)
      .then(this.onPlanetLoaded);
  }

И немного изменяем деструктуризацию

const { planet: {id, name, population,
      rotationPeriod, diameter} } = this.state;

Всё работает.


Выводы

1. Изолируйте код, который обрабатывает данные
2. Отделяйте модель данных API от модели данных приложения