Komunikacja z serwerem

Do odczytu/zapisu danych wykorzystujemy "Obietnice" (Promise). Na przykład przy wykorzystaniu biblioteki axios (wymaga doinstalowania):

import axios from 'axios';

axios(ADRES_URL).then(
 (response, err) => {
   callBack(response.data);
  }
)

Pełna obsługa musi zawierać reakcję na błędy:

const throwError = message => {
  console.error(message);
  alert(message);
  throw Error(message);
}

export const getData = (callBack) => {
 axios(ADRES_URL).then(
  (response) => {
      callBack(response.data);
  }
 ).catch(
      throwError
 )
}

Wykorzystanie tej funkcji może wyglądać następująco:

class App extends Component {

 przeczytano = (dane) => {
  this.setState({...this.state, dane: dane});
 }

 odczyt = () => {
   getData(this.przeczytano);
}

Pewnym uproszczeniem jest użycie składni async/await (która jest tylko innym sposobem zapisu Obietnic (zob. https://www.nafrontendzie.pl/skladnia-async-await-nowy-sposob-na-promisy\.

async function getData() {
  try {
    const response = await axios(ADRES_URL);
    return response.data;
  } catch (error) {
    throwError(error);
  }
}

Zapis ze składnią async/await jest równoważny poprzedniemu, ale nie musimy uruchamiać tutaj funkcji callBack.

Oto kompletny przykład komponentu:

import React, { Component } from 'react';
import axios from 'axios';

const ADRES_URL = 'https://books.otwartaedukacja.pl/books';

const throwError = message => {
  console.error(message);
  alert(message);
  throw Error(message);
}

async function getBooksAA() {
  try {
    const response = await axios(ADRES_URL);
    return response.data;
  } catch (error) {
    throwError(error);
  }
}

class App extends Component {

  constructor() {
    super();
    this.state = { dane : [] }
  }

  przeczytano = (dane) => {
    this.setState({...this.state, dane: dane});
  }

  odczyt = async () => {
    const dane = await getBooks();
    if (dane) this.przeczytano(dane);
  }

  render() {
    return <div>
      <button onClick={ this.odczyt }>Odczyt</button>
      <div>{
          this.state.dane &&
          this.state.dane.map(function (book, index) {
            return <div>{index}: {book.title}</div>
          })
       }
      </div>
    </div>;
  }

}

zobacz przykład [034]

API obługujące komunikację może przechwytywać błędy (nie tylko związane z transmisją) i nawet w przypadku błędu kończyć działanie z sukcesem (HTTP 200), ale zwracać dane w postaci {"errors": ..., "message": ...}. Wtedy obsługa błędów będzie nieco inna:

async function getBooksAA(request) {
    const response = await request();
    if (response.data.errors) {
      // Błąd zwrócony jako HTTP 200, {"errors": ..., "message": ...}
      throwError(response.data.message);
    }    
    return response.data;
}

Zobacz kompletny przykład (uwzględniający różne przypadki: [035]