Napisałem wcześniej podobne artykuły na temat AngularJS (link) i Angular2 (link). Wiedza tam zawarta jest w dużej części uniwersalna i możesz chcieć do nich zajrzeć.
Komunikacja w React.js
React to prosta biblioteka. Zasadniczo nie obchodzi jej w jaki sposób projektujesz architekturę swojej aplikacji. Ale zawarto w niej mechanizm na przekazywanie informacji z jednego komponentu do drugiego — z rodzica do dziecka — przy pomocy propsów. Tak jak robiliśmy to do tej pory. Ale przekazywać można nie tylko dane, ale też funkcje ;) W tym wpisie fragmenty kodu, a całość razem z testami znajdziesz na moim GitHubie: mmiszy/typeofweb-kurs-react/tree/part-4.
Rodzic ➜ Dziecko: Propsy
Rodzic przekazuje do swoich dzieci dane. Przykładowo: Aplikacja zawiera listę kontaktów, które muszą zostać przekazane do komponentu-dziecka, który je wyświetli. Znana sytuacja, prawda? ;)
React informuje nas, że propsy się zmieniły poprzez funkcję componentWillReceiveProps(nextProps) — dzięki czemu można zareagować na zmiany danego propsa. Ale raczej tego nie rób. Bo naprawdę rzadko jest to potrzebne. Troszkę więcej o tym w jednym z poprzednich wpisów:

Metody cyklu życia komponentu w React.js
Przy okazji omawiania komponentów będących klasami w React.js, wspomniałem też o możliwości korzystania z metod cyklu życia (lifecycle methods). Chciałbym do tego tematu teraz powrócić. Pokażę jakie metody cyklu życia definiuje React.js, do czego one służą i kiedy mogą się przydać.
W zasadzie to cała filozofia.
Dziecko ➜ Rodzic: Propsy (callback)
A teraz inna sytuacja. Coś się wydarzyło w komponencie-dziecku i musisz poinformować o tym rodzica. Przykładowo: Na naszej liście kontaktów, użytkownik zaznaczył kontakt, a rodzic musi wiedzieć, który kontakt został zaznaczony. Jak to zrobić?
React nie ma two-way data bindingu (jak AngularJS, Angular czy Vue). W tym przypadku to dobrze — bo komunikacja za pośrednictwem tego sposobu często prowadzi do bałaganu. Reactowy sposób jest inny: Rodzic może przekazać do dziecka funkcję. Następnie dziecko wywoła tę funkcję, gdy zechce poinformować rodzica o zmianach. To jest tak proste jak brzmi. Na przykładzie z listą kontaktów:
Dodaję nowe pole do state w App: selectedUser — będę tutaj przechowywał użytkownika, który został zaznaczony. Następnie wyświetlam go wewnątrz funkcji render. Pozostały kod pozostawiam bez zmian:
class App extends React.Component {
  constructor() {
    super();
    this.state = {
      filteredUsers: allUsers,
      selectedUser: null // tutaj
    };
  }
  render() {
    return (
      <div>
        {this.state.selectedUser}
        {/* … */}
      </div>
    );
  }
}
Teraz czas na przekazanie funkcji do dziecka. Tworzę więc nową funkcję w tym komponencie i przekazuję ją niżej:
onUserSelected = (selectedUser) => {
  this.setState({
    selectedUser
  });
}
render() {
  return (
    <div>
      {/* … */}
      <UsersList userSelected={this.onUserSelected} users={this.state.filteredUsers} />
    </div>
  );
}Teraz modyfikuję UsersList i wywołuję w nim userSelected gdy użytkownik kliknie na kontakt:
<li onClick={userSelected.bind(null, user)} key={user}>{user}</li>Dowolny komponent ➜ Inny Komponent
Tutaj magia Reacta się kończy ;) No, prawie, ale na temat context opowiem innym razem. Załóżmy na razie, że nie istnieje ;) Jak więc skomunikować ze sobą dwa komponenty, które leżą sobie gdziekolwiek w aplikacji? Na dowolny znany Ci sposób. To nie żart. Oto kilka wskazówek:
- stwórz funkcję / klasę / obiekt — tzw. serwis, który posłuży Ci do komunikacji. Zaimportuj i użyj go w obu komponentach.
- Przechowuj w nim dane lub wywołuj funkcje — podobnie jak w przypadku komunikacji rodzic ⟺ dziecko
- Przyda Ci się znajomość wzorców projektowych, np. wzorca obserwatora. Więcej na temat samej koncepcji pod koniec mojego innego wpisu (link). Może ten gist (link) się nada?
- Możesz użyć gotowych paczek, typu EventEmitter3 (link) lub podobnych.
Flux, Redux, MobX i co tam jeszcze…
Są też pewne ciekawe, rozbudowane i popularne rozwiązania: Architektura Flux i wywodzący się z niej słynny Redux, a także MobX. No i inne podobne biblioteki. Popełniłem już wcześniej jeden wpis na temat Fluksa i Reduksa od strony architektury. Jeśli hasła CQRS albo Event Sourcing nie są Ci obce to śmiało czytaj:

Flux i Redux: globalny store i jednokierunkowy przepływ danych
Na co dzień korzystam z Redux razem z React. Dawniej używałem też własnej implementacji architektury Flux razem z AngularJS. Postanowiłem napisać o tym koncepcie coś więcej — bo jest to bez wątpienia bardzo ciekawe! Jednokierunkowy przepływ danych, akcje, dispatcher, action creator, reducer… to wszystko w tym wpisie :) A do…
Natomiast w kontekście Reacta — wrócę do tego, obiecuję ;) To temat pierwszy albo drugi wpis po tym! zapisz się na szkolenie z React.
Podsumowanie
Teraz już wiesz jak komponenty rozmawiają ze sobą. Wiedza na temat architektury aplikacji i wzorców projektowych przydaje się zawsze, niezależnie od frameworka, z którego korzystasz. Także tutaj. Ponownie — cały kod wraz z testami jest dostępny na moim GitHubie: https://github.com/mmiszy/typeofweb-kurs-react/tree/part-4
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:  Użyj biblioteki EventEmitter3 aby skomunikować ze sobą App i UsersList w powyższym przykładzie (bez przekazywania funkcji jako props). Czy udało Ci się bez problemu? Napisz w komentarzu!
