LEKCJA 02 - REACT (p) - state, events

LEKCJA 02 - REACT (p) - state, events
ukryj menu
SPEC
aktualizacja: 2021-09-14 10:19:32

1. state - lokalny stan komponentu

- dzięki state każda instancja komponentu może posiadać własne, prywatne dane
- props po dodaniu do komponentu są niemodyfikowalne
- state jest skonstruowany do przechowywania i stosowania zmian w komponencie


budowa konstruktora klasy, z danymi w postaci obiektu state

w konstruktorze klasy komponentu często przekazujemy props z nadrzędnego komponentu
po to aby je móc wykorzystywać dalej


constructor(props) {

    super(props);
    console.log(props);

    this.state = {a:1};
}kopiuj



przykład klasy i wykorzystania w niej obiektu state

class Square extends React.Component {
  constructor(props) {
    super(props);
    this.state = {a:1, b:2};
  }

  render() {
    return (
     
        div
           a = {this.state.a}, b = {this.state.b}
        /div
     
    );
  }
}kopiuj


state zmieniamy/ustawiamy za pomocą funkcji setState

changeState() {
    this.setState({
      a: Math.random() * 100,
      b: Math.random() * 100,
    });
}kopiuj


poprawne użycie funkcji changeStates() powinno nastąpić w konstruktorze klasy
po to aby móc w niej używać obiektu this


this.changeState = this.changeState.bind(this);kopiuj

a wywołanie kliknięcia w butonie

<button onClick={this.changeState}>kopiuj

Dlaczego piszemy super(props)?

https://overreacted.io/pl/why-do-we-write-super-props/kopiuj



2. różne sposoby używania funkcji w komponentach


a) bindowanie this w konstruktorze - zalecane, wydajne

class Square extends React.Component {
   constructor(props) {
      super(props);
      this.clickMe = this.clickMe.bind(this);
  }
  clickMe() {
      console.log('ok');
  }
  render() {
      return <button onClick={this.clickMe}>click me</button>;
  }
}kopiuj



b) bind this w render (słabsza wydajność, z powodu utworzenia nowej funkcji dla każdej instancji komponentu)


class Square extends React.Component {
  clickMe() {
    console.log('ok');
  }
  render() {
    return <button onClick={this.clickMe.bind(this)}>click me</button>;
  }
}kopiuj



c) arrow function w render (ładna konstrukcja, słabsza wydajność, z powodu utworzenia nowej funkcji dla każdej instancji komponentu)


class Square extends React.Component {
  clickMe() {
    console.log('ok');
  }
  render() {
    return <button onClick={() => this.clickMe()}>click me</button>;
  }
}kopiuj



d) niepoprawne wywołanie funkcji dla każdej instancji komponentu

w poniższym przypadku funkcja wywoła się od razu przy tworzeniu komponentu (nawiasy!) - błąd

render() {
  return <button onClick={this.clickMe()}>click me</button>
}kopiuj


e) poprawne wywołanie funkcji - funkcja jest argumentem, przekazanym do props

w poniższym przypadku funkcja wywoła się dopiero po kliknięciu butona

render() {  
  return <button onClick={this.clickMe}>click me</button>
}kopiuj


f) najnowszy sposób definiowania funkcji w klasie, poza konstruktorem

clickMe = () => console.log("test")kopiuj

wymaga najnowszych wersji Babla, obsługującej tzw class properties



dokładniejsza i ciekawa analiza:

https://medium.com/@charpeni/arrow-functions-in-class-properties-might-not-be-as-great-as-we-think-3b3551c440b1kopiuj

3. jak przekazywać argumenty do funkcji?

dla funkcji :

clickMe(param) {
    console.log(param)
}kopiuj


stosujemy kliki:

<button onClick={this.clickMe.bind(this,"data")} />kopiuj

lub

<button onClick={() => this.clickMe("data")} />kopiuj


4. lifecycle komponentu Reacta

poniższe wbudowane zdarzenia są wykorzystywane do pobierania danych zewnętrznych, startowania / stopowania interwałów, zwalniania zasobów
w kolejnych wersjach Reacta są dodawane nowe, a usuwane inne zdarzenia

przykładowe zdarzenie w czasie życia komponentu React



componentDidMount() // po utworzeniu komponentu, po konstruktorze
componentDidUpdate() // nie wywoływany podczas pierwszego rendera, tylko po aktualizacjikopiuj


przykład zastosowania


class Clock extends React.Component {
 
  componentDidMount() {
    // zmiana state bez kliknięcia butona

  }

}kopiuj


5. Uwaga: state jest aktualizowany asynchronicznie


jeśli chcemy wykonać jakąś funkcję na aktualnym state

constructor() {
    super()
    this.state = {
        x: false
    }
}
componentDidMount()  {
    console.log("initial state - > " + this.state.x)
    this.setState({
        x: true
    },
     () => console.log("state already updated - > " + this.state.x)
    )
    console.log("state not updated yet -> " + this.state.x)
};
kopiuj

6. ćwiczenie 01 - React state - start

w konstruktorze klasy Square

this.state = {a:1, b:2, c: 3};kopiuj

w render
   
<h1>a = {this.state.a} </h1>kopiuj
                
7. ćwiczenie 02 - React state - setState

w konstruktorze ustawiamy states

constructor() {           
            super();
            this.state = {
                stan: ...
            };
            this.onButtonClick = this.onButtonClick.bind(this)
        }kopiuj


w kliku podmieniamy

onButtonClick() {
            if(this.state.stan == ...)
                this.setState({
                   ...
                });
            else{ ... }


}kopiuj


<button onClick={this.onButtonClick}>klik</button>kopiuj


8. cwiczenie 03 - React state - state of all components

ćwiczenie jest przykładem komunikacji jednokierunkowej : parent - > child

wykonaj dwa komponenty : Food i FoodList

mając tablicę w obiekcie state komponentu FoodList:


["masło", "mleko", "chleb", "dżem"];kopiuj


w onButtonClick () losuj jej element i ustawiaj go w state (setState)

w każdej instancji komponentu Food przekazuj ten state jako prop


<Food food={ this.state.randomFood }/>kopiuj

wewnątrz każdego komponentu wyświetlaj wylosowany ten sam food

Uwaga: na starcie pokaż w komponentach pierwszy element z tablicy


9. cwiczenie 04 - React state - private state of component

rozbudowa poprzedniego ćwiczenia, o buton wewnątrz komponentu Food
Buton zmienia stan polubienia jedzenia danego przez rodzica


10. cwiczenie 05 - React state - add component

opis:
Mamy dwa komponenty: Child (obrazek) i Parent (lista obrazków)
Kliknięcie jednego lub drugiego butona dodaje dane o obrazku do wyjściowej tablicy dwu stringów ["hamburger","trufle"], która jest przechowywana w state Parenta.

Funkcja dodająca jest wywoływana z argumentem tanie lub drogie
W komponencie Parent jest renderowana tablica komponentów Child


11. cwiczenie 06 - React state - random styles

w konstruktorze ustaw states w,h,c jak na rysunku

this.state = {w:100, h:100, c: 100};kopiuj

zbinduj funkcję obsługującą klika

w tej funkcji ustawiaj setState

this.setState({
   w: losowa wielkość,
   h: losowa wielkość,
   c: "#losowy kolor"
})kopiuj



przykład zmiany wybranego stylu css w render

<div className="div" style={
   {
      height: this.state.h + 'px',
      background:this.state.c
   }
                 
   }> kopiuj
 

12. ćwiczenie 07 - React state - timer simple

do utworzenia jest komponent Timer

w klasie Timer zbinduj this


this.onButtonClick = this.onButtonClick.bind(this)kopiuj

metoda zmieniająca stan, wywoływana w kliku

setTimer() {
            this.setState({
                licznik: this.state.licznik - 1
            })
            if(...) {
                clearInterval(this.intervalId);
            }
}kopiuj


metoda startuje w kliku

onButtonClick() {
   this.intervalId = setInterval(this.setTimer.bind(this), 1000);
}kopiuj


button

<button onClick={ this.onButtonClick}>klik</button>kopiuj

13. zadanie 08 - React state - stopers

a) schemat działania podobny do poprzedniego ćwiczenia
należy startować i stopować interval
każdy stoper działa niezależnie

b) w miarę wolnego czasu: stoper z dziesiątymi częściami sekundy