- React.js: Wprowadzenie do kursu od podstaw
- Poznaj React.js
- Pierwszy komponent w React.js
- Props czyli atrybuty w React.js
- Podział na komponenty w React.js
- Klasy jako komponenty React.js
- Interakcja z komponentami React.js
- Stan komponentów React.js
- State w React.js 2
- Metody cyklu życia komponentu w React.js
- React.js w przykładach: filtrowanie statycznej listy
- Tworzenie aplikacji React.js dzięki create-react-app
- React.js na GitHub Pages dzięki create-react-app
- Testowanie aplikacji React.js — podstawy Enzyme
- Testowanie React.js w Enzyme — props, state i interakcje
- Poprawne bindowanie funkcji w React.js
- Odpowiadam na pytania: Babel, ECMAScript, destrukturyzacja, onClick, className
- Komunikacja pomiędzy komponentami w React.js
- Komunikacja z API w React.js
- Formularze w React.js — kontrolowane komponenty
- Formularze w React.js — niekontrolowane komponenty
- Odpowiadam na pytania: props, nawiasy klamrowe, funkcje vs klasy, import react
- TDD w React.js z pomocą react-testing-library
- Flux i Redux: globalny store i jednokierunkowy przepływ danych
- React + Redux — kurs: wprowadzenie i podstawy
- React + Redux — filtrowanie listy, proste selektory
- Projektowanie komponentów: Presentational & Container Components
- Asynchroniczność w Redux: redux-thunk
- Kiedy używać state, a kiedy Redux?
- Nowe metody cyklu życia: getDerivedStateFromProps i getSnapshotBeforeUpdate
- Leniwe ładowanie komponentów w React dzięki import
- Higher Order Reducers — Redux i powtarzanie kodu
- React Hooks — wprowadzenie i motywacja
- React Hooks: useState, czyli stan w komponentach funkcyjnych
- React Hooks: useState — wiele stanów, callbacki i inne niuanse
- React Hooks: useEffect — efekty uboczne w komponencie
- React Hooks a żądania do API
- useReducer — przenoszenie logiki poza komponent
- useMemo, useCallback, czyli rozwiązanie problemów ze zmieniającymi się propsami
- Wady React Hooks
- React Hooks: Piszemy własne hooki!
Bardzo często powracającym wątkiem jest pytanie o to, w jaki sposób zaimplementować komunikację z API w React.js. Moja odpowiedź może Cię nieco zaskoczyć: React nie ma nic do tego. Możesz to robić absolutnie dowolnie.
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/mmiszy/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é[email protected]",
"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 rounded image" 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: Poznaj React w dwa dni na naszym szkoleniu!
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/mmiszy/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).
- React.js: Wprowadzenie do kursu od podstaw
- Poznaj React.js
- Pierwszy komponent w React.js
- Props czyli atrybuty w React.js
- Podział na komponenty w React.js
- Klasy jako komponenty React.js
- Interakcja z komponentami React.js
- Stan komponentów React.js
- State w React.js 2
- Metody cyklu życia komponentu w React.js
- React.js w przykładach: filtrowanie statycznej listy
- Tworzenie aplikacji React.js dzięki create-react-app
- React.js na GitHub Pages dzięki create-react-app
- Testowanie aplikacji React.js — podstawy Enzyme
- Testowanie React.js w Enzyme — props, state i interakcje
- Poprawne bindowanie funkcji w React.js
- Odpowiadam na pytania: Babel, ECMAScript, destrukturyzacja, onClick, className
- Komunikacja pomiędzy komponentami w React.js
- Komunikacja z API w React.js
- Formularze w React.js — kontrolowane komponenty
- Formularze w React.js — niekontrolowane komponenty
- Odpowiadam na pytania: props, nawiasy klamrowe, funkcje vs klasy, import react
- TDD w React.js z pomocą react-testing-library
- Flux i Redux: globalny store i jednokierunkowy przepływ danych
- React + Redux — kurs: wprowadzenie i podstawy
- React + Redux — filtrowanie listy, proste selektory
- Projektowanie komponentów: Presentational & Container Components
- Asynchroniczność w Redux: redux-thunk
- Kiedy używać state, a kiedy Redux?
- Nowe metody cyklu życia: getDerivedStateFromProps i getSnapshotBeforeUpdate
- Leniwe ładowanie komponentów w React dzięki import
- Higher Order Reducers — Redux i powtarzanie kodu
- React Hooks — wprowadzenie i motywacja
- React Hooks: useState, czyli stan w komponentach funkcyjnych
- React Hooks: useState — wiele stanów, callbacki i inne niuanse
- React Hooks: useEffect — efekty uboczne w komponencie
- React Hooks a żądania do API
- useReducer — przenoszenie logiki poza komponent
- useMemo, useCallback, czyli rozwiązanie problemów ze zmieniającymi się propsami
- Wady React Hooks
- React Hooks: Piszemy własne hooki!
Mam problem z zapisaniem danych w state po pobraniu fetch’em, możliwe, że dane w ogóle się nie pobierają z zewnętrznego API
Zamieszczam kod, jakieś pomysły? 🙂
https://github.com/mjaracz/ReactFetch
Cześć Michał!
Przesłałem na githuba, teraz widać dobrze cała strukturę, masz jakiś pomysł czemu, items zwraca null
Na początku sam ustawiasz null: https://github.com/mjaracz/ReactFetch/blob/master/src/App.js#L10-L12
A tutaj nadal brakuje .results. Powinno być json.results. https://github.com/mjaracz/ReactFetch/blob/master/src/App.js#L18
Ten kod w ogóle nie działa na Codepenie, na pewno wszystko poprawnie ustawiłeś?
Patrząc na szybko to po prostu masz literówkę — json.resulte zamiast json.results.
nie działa na codepenie, ponieważ skopiowałem każdy komponent do jednego skryptu. każdy komponent taki jak
był zapisany w osobnym pliku i imporotwany do app.js, zrobiłem tak bo nie chciało mi sie kopiować każdgo komponentu do osobnego codepena
za chwile psrawdze to literowke
[…] Komunikacja z API w React.js […]
Witam, trafiłem tutaj na „schody”. Wszystko działa ładnie, ale gdy próbuję dać do fetch’a zamiast adresu do generowania jsona dać swojego z dysku wyskakuje mi:
Unhandled Rejection (SyntaxError): Unexpected token < in JSON at position 0 Próbowałem różnych jsonów, nawet pobrałem jeden z wygenerowanych jsonów, i ciągle to samo. Czy importowanie z dysku się czymś różni ? Pozdrawiam
EDIT: Poradziłem sobie, rozwiązanie było banalne (o ile dobre) usunąłem całkiem fetcha z componentDidMount i po prostu dodałem this.setState i przypisałem zaimportowany JSON. działa 🙂
Cześć,
Mam takie pytanie, ponieważ szukam po różnych forach i nie mogę znaleźć działającej odpowiedzi.
W jaki sposób można wywołać funkcję w stylu onInit lub $(document).ready w React?
Chodzi o sytuację, gdzie w ComponentDidMount używam fetch aby pobrać dane z api i wyświetlić je na stronie i potem automatycznie zaraz po ich załadowaniu wykonać akcję np. zablokowania/odblokowania buttonów na podstawie danych z poszczególnych pól wyświetlanych na ekranie.
W każdy jeden sposób w jaki próbuję to zrobić najpierw wywoływana jest funkcja a dopiero potem dane są renderowane na stronie, więc wszystkie argumenty jakie są brane pod uwagę w tym czasie są jeszcze nullem.
przykład funkcji:
componentDidMount(){
fetch(….); // tutaj działa wszystko poprawnie
prepareButtons();
}
prepareButtons(){
if(this.state.myObject.name == null){
alert(this.state.myObject.name); // tutaj dla sprawdzenia jaka wartośc wchodzi w sprawdzenie ifa -> zawsze pokazuje null
document.getElementById(„changeNameButton”).setAttribute(„disabled”, „true”);
}
}
W sytuacji kiedy nawet wartość nie jest nullem (co widać w konsoli i na stronie po załadowaniu) funkcja widzi ją jako null ponieważ zawsze wykonuje się ona zanim wszystkie pola zostaną uzupełnione.
Dziękuję
Pozdrawiam
Po wykonaniu fetcha, wewnątrz funkcji
then
, powinieneś użyćthis.setState
, tak jak to opisałem w tym artykule 🙂Nie powinieneś używać żadnego
document.getElementById
, bo Twoje zmiany i tak zostaną nadpisane przez Reacta przy najbliższym renderze.Cześć Michał.
Można ten guzik zrobić w ten sposób?
W tym przypadku może to zadziała, ale czy to brzmi sensownie?
componentDidMount
wywołuje się gdy komponent jest montowany.Hej, mam problem z zastosowaniem powyższego przykładu w mojej aplikacji. Otóż moje API zwraca mi taki obiekt:
{
„NumberOfPln”: 366814918.794,
„NumberOfBtc”: 1900.00208,
„NumberOfBcc”: 109.17164,
„NumberOfEth”: 0,
„NumberOfLtc”: 0.41808
}
Jest to API udostępnione przez localhost, taki wynik otrzymuję po wpisaniu zapytania (http://localhost:9000/api/transactions/account?id=1) typu get w Postman.
Piszę więc w React:
class App extends Component {
state = {
status: []
};
componentDidMount = () => {
fetch(„http://localhost:9000/api/transactions/account?id=1”)
.then(res => res.json())
.then(json => this.setState({
status: json.results
}));
}
render() {
console.log(this.state.status);
return(
)
}
}
export default App;
Otrzymuję w console log undefined…. Co robię źle? I jak tutaj „wyciągnąć potem pojedyncze wartości, czy wystarczy np. status.NumberOfPln?
A skąd json.results? Nie powinno być samo json?
Wielkie dzięki Michał. Sama siedziałam nad tym cały wieczór i nie widziałam!
Polecam się!
[…] Komunikacja z API w React.js […]
Mógłbyś wstawić gdzieś przykład z tym ćwiczeniem eventemitter?
Pozdrawiam 😉
Możesz gdzieś wstawić przykład ćwiczenia z eventemitter?