Plan
Rozpatrzę teraz popularny przypadek: W momencie załadowania aplikacji, potrzebuję pobrać jakieś dane z API. Gdy już będą gotowe — chcę je wyświetlić. Brzmi dobrze? Rozbuduję więc swój poprzedni przykład: Znaną i lubianą listę kontaktów ;)
Wracam do kodu stąd:
Gotowa implementacja z tej części kursu dostępna jest tutaj: github.com/typeofweb/typeofweb-kurs-react/tree/contacts-list-1
Przygotowanie
Nieco zmieniam tamten przykład. Przede wszystkim to komponent App
będzie „dostarczycielem” danych do ContactsList
. Przekaże tablicę jako props
:
export const App = () => {
return (
<div>
<AppHeader />
<main className="ui main text container">
<ContactsList contacts={[]} />
</main>
</div>
);
};
Tę tablicę za moment wypełnię danymi z API. Przykładowy obiekt z API wygląda tak:
{
"gender": "female",
"name": { "title": "mrs", "first": "célia", "last": "lopez" },
"location": {
"street": "3403 rue paul-duvivier",
"city": "dunkerque",
"state": "var",
"postcode": 52018
},
"email": "célia.lopez@example.com",
"login": {
"username": "purplelion429",
"password": "spoiled",
"salt": "nUY17qZz",
"md5": "2660f36114ad97ebbb38729d1e1ad935",
"sha1": "14e893bf4d76c2e6bc942846d557acc3c1fa3223",
"sha256": "d032a528a2da82f5b9ef37d3c3277c9255fef5de73db1e979402c2ee86fe4cf2"
},
"dob": "1956-01-28 09:02:34",
"registered": "2011-05-16 19:04:38",
"phone": "04-98-07-66-00",
"cell": "06-33-63-47-98",
"id": { "name": "INSEE", "value": "256045054319 82" },
"picture": {
"large": "https://randomuser.me/api/portraits/women/80.jpg",
"medium": "https://randomuser.me/api/portraits/med/women/80.jpg",
"thumbnail": "https://randomuser.me/api/portraits/thumb/women/80.jpg"
},
"nat": "FR"
}
Ja chciałbym z tego wyciągnąć:
- pełne imię i nazwisko
- numer telefonu
- link do avatara
- coś unikalnego co posłuży za atrybut
key
(wymagany przy tablicach elementów)
Wymaga to tylko wyjęcia i połączenia niektórych pól:
const avatarUrl = contact.picture.thumbnail;
const { title, first, last } = contact.name;
const name = `${title} ${first} ${last}`.trim();
const phone = contact.phone;
const key = contact.login.username;
Ostatecznie cały komponent:
export class ContactsList extends React.Component {
contactToContactItem = (contact) => {
const avatarUrl = contact.picture.thumbnail;
const { title, first, last } = contact.name;
const name = `${title} ${first} ${last}`.trim();
const phone = contact.phone;
return <ContactItem key={key} avatarUrl={avatarUrl} name={name} phone={phone} />;
};
render() {
return <ul className="ui relaxed divided list selection">{this.props.contacts.map(this.contactToContactItem)}</ul>;
}
}
Nic nadzwyczajnego, to wszystko już na pewno widziałaś/eś w poprzednich odcinkach kursu. Idźmy dalej… został tylko jeden komponent, który wyświetla podane informacje:
export const ContactItem = ({ avatarUrl, name, phone }) => {
return (
<li className="item">
<img src={avatarUrl} className="ui mini image rounded" alt="" />
<div className="content">
<h4 className="header">{name}</h4>
<div className="description">{phone}</div>
</div>
</li>
);
};
Uff! To tyle jeśli chodzi o przygotowania.
Pobieranie danych z REST API w React.js
Do sedna! Chcę pobierać listę kontaktów z API randomuser.me. Potrzebne mi będzie jedno żądanie GET
. Najprościej zrobić je przy pomocy fetch
wbudowanego w przeglądarkę :)
Jak wspomniałem wcześniej, dobrym miejscem na wykonanie pytania do API jest funkcja componentDidMount(…)
. Tam też umieszczę swój kod. Wykonam żądanie, poczekam na odpowiedź, a wynik zapiszę w state
. Następnie przekażę to do komponentu ContactsList
:
export class App extends React.Component {
state = {
contacts: [],
};
componentDidMount() {
fetch('https://randomuser.me/api/?format=json&results=10')
.then((res) => res.json())
.then((json) => this.setState({ contacts: json.results }));
}
render() {
return (
<div>
<AppHeader />
<main className="ui main text container">
<ContactsList contacts={this.state.contacts} />
</main>
</div>
);
}
}
Działa!
Spinner na czas ładowania…
No tak, działa, ale jednak efekt nie jest idealny. Początkowo renderuje się zupełnie pusta lista, a dopiero po chwili pojawiają się dane. Zmienię to. Chcę, aby na początku wyświetlał się napis Ładowanie…
:
{
contacts ? <ContactsList contacts={contacts} /> : 'Ładowanie…';
}
Korzystam z faktu, że wyrażenia wewnątrz {
i }
w JSX są wykonywane niemal jak zwykły JavaScript — i mogę tutaj użyć operatora trójoperandowego. W prawdziwej aplikacji zamiast napisu Ładowanie…
prawdopodobnie chciałbym dodać jakiś spinner, który zamknąłbym np. w LoadingComponent
:)
Możemy Cię nauczyć tego wszystkiego szybciej: zapisz się na szkolenie z React.
Podsumowanie
Poznałaś/eś właśnie podstawowy sposób pobierania i wyświetlania danych z REST API w React.js. To nie było takie trudne, prawda? Cały kod: github.com/typeofweb/typeofweb-kurs-react/tree/contacts-list-1
Jeśli chcesz na bieżąco dowiadywać się o kolejnych częściach kursu React.js to koniecznie śledź mnie na Facebooku i zapisz się na newsletter.
Ćwiczenie
Ćwiczenie: Dodaj do aplikacji guzik „odśwież”, który spowoduje ponowne pobranie i wyrenderowanie listy kontaktów (dane z randomuser.me są losowe, więc za każdym razem będą inne).