Czy możesz wymusić ponowne wysłanie komponentu React bez wywoływania setState?


690

Mam zewnętrzny (do komponentu), obserwowalny obiekt, na którym chcę nasłuchiwać zmian. Gdy obiekt jest aktualizowany, emituje zdarzenia zmiany, a następnie chcę ponownie wysłać komponent po wykryciu jakiejkolwiek zmiany.

W przypadku najwyższego poziomu React.renderbyło to możliwe, ale w komponencie nie działa (co ma sens, ponieważ rendermetoda zwraca obiekt).

Oto przykład kodu:

export default class MyComponent extends React.Component {

  handleButtonClick() {
    this.render();
  }

  render() {
    return (
      <div>
        {Math.random()}
        <button onClick={this.handleButtonClick.bind(this)}>
          Click me
        </button>
      </div>
    )
  }
}

Kliknięcie przycisku wywołuje wewnętrznie this.render(), ale to nie jest to, co faktycznie powoduje renderowanie (możesz to zobaczyć w działaniu, ponieważ tekst utworzony przez {Math.random()}nie zmienia się). Jednakże, jeśli po prostu zadzwonić this.setState()zamiast this.render(), to działa dobrze.

Tak więc myślę, że moje pytanie brzmi: czy komponenty React muszą mieć stan, aby móc ponownie wysłać? Czy istnieje sposób zmuszenia komponentu do aktualizacji na żądanie bez zmiany stanu?


7
odpowiedź Zaakceptowany mówi this.forceUpdate()jest dobrym rozwiązaniem, natomiast reszta wszystkich odpowiedzi i kilka uwag są przed stosowaniem forceUpdate(). Czy w takim razie można powiedzieć, że pytanie nie uzyskało jeszcze właściwego rozwiązania / odpowiedzi?
adi

6
Wyjątkowa odpowiedź odpowiedziała wówczas na moje pytanie. Czy technicznie jest to odpowiedź, której szukałem i nadal uważam, że jest to właściwa odpowiedź. Inne odpowiedzi, które moim zdaniem są dobrą informacją uzupełniającą dla osób z tym samym pytaniem, o których należy pamiętać.
Philip Walton,

Interesujące jest to, że NIE POTRZEBUJESZ ŻADNEGO INNEGO STANU poza inicjowaniem go do zwykłego obiektu, a następnie wywołanie this.setState ({}) po prostu wyzwala nowy rendering. Reakcja jest świetna, ale czasem dziwna. Dlatego możesz bezpośrednio zapętlać dane w magazynie, gdy wywołasz zmianę bez dodatkowej hydrauliki lub martwisz się o dane przypadające na instancję komponentu.
Jason Sebring

Ogólnie powiedziałbym „tak”. Jeśli używasz wymuszonej aktualizacji, służy to do aktualizacji składników, w których mogą one zależeć od zmian poza zarządzaniem stanem aplikacji. Nie mogę wymyślić dobrego przykładu. Warto wiedzieć.
Daniel

Odpowiedzi:


765

W swoim komponencie możesz zadzwonić w this.forceUpdate()celu wymuszenia ponownego wydania.

Dokumentacja: https://facebook.github.io/react/docs/component-api.html


169
Innym sposobem jest this.setState (this.state);
kar

25
Nie zaleca się używania forceupdate, proszę zobaczyć ostatnią odpowiedź.
Varand Pezeshkian

42
Chociaż this.forceUpdate()nie jest to bardzo dobre rozwiązanie problemu pytających, jest to prawidłowa odpowiedź na pytanie postawione w tytule. Chociaż ogólnie należy tego unikać, istnieją sytuacje, w których forceUpdate jest dobrym rozwiązaniem.
ArneHugo

8
@kar W rzeczywistości można zaimplementować dodatkową logikę, aby uczynić shouldComponentUpdate()swoje rozwiązanie bezużytecznym.
Qwerty

4
Przekroczono maksymalny rozmiar stosu wywołań
IntoTheDeep

326

forceUpdatenależy tego unikać, ponieważ odbiega on od sposobu myślenia React. Dokumenty React przytaczają przykład, kiedy forceUpdatemożna go użyć:

Domyślnie, gdy zmieni się stan lub rekwizyty komponentu, komponent zostanie zrenderowany. Jeśli jednak zmiany te zostaną niejawnie (np. Dane głęboko w obiekcie zmienią się bez zmiany samego obiektu) lub jeśli metoda render () zależy od niektórych innych danych, można poinformować React, że należy ponownie uruchomić render (), wywołując wymusić aktualizację().

Chciałbym jednak zaproponować pomysł, że nawet przy głęboko zagnieżdżonych obiektach nie forceUpdatejest potrzebny. Dzięki zastosowaniu niezmiennego źródła danych zmiany stają się tanie; zmiana zawsze spowoduje powstanie nowego obiektu, dlatego musimy tylko sprawdzić, czy zmieniło się odwołanie do obiektu. Możesz użyć biblioteki Immutable JS, aby zaimplementować niezmienne obiekty danych w swojej aplikacji.

Zwykle powinieneś starać się unikać wszelkich zastosowań forceUpdate () i czytać tylko z this.props i this.state w render (). Dzięki temu Twój komponent jest „czysty”, a aplikacja znacznie prostsza i wydajniejsza. wymusić aktualizację()

Zmiana klucza elementu, który chcesz ponownie renderować, zadziała. Ustaw rekwizyt klucza na elemencie poprzez stan, a następnie, gdy chcesz zaktualizować ustaw stan, aby mieć nowy klucz.

<Element key={this.state.key} /> 

Następnie następuje zmiana i resetujesz klucz

this.setState({ key: Math.random() });

Chcę zauważyć, że zastąpi to element, który zmienia klucz. Przykładem tego może być pole wprowadzania pliku, które chcesz zresetować po przesłaniu obrazu.

Chociaż prawdziwa odpowiedź na pytanie PO byłaby taka forceUpdate(), znalazłem to rozwiązanie pomocne w różnych sytuacjach. Chcę również zauważyć, że jeśli używasz, forceUpdatemożesz przejrzeć kod i sprawdzić, czy jest inny sposób na zrobienie tego.

UWAGA 1-9-2019:

Powyższe (zmiana klucza) całkowicie zastąpi element. Jeśli znajdziesz klucz do wprowadzenia zmian, prawdopodobnie masz problem z innym kodem. Użycie Math.random()klucza spowoduje ponowne utworzenie elementu przy każdym renderowaniu. NIE zalecałbym aktualizacji klucza w ten sposób, ponieważ zareaguj używa klucza do określenia najlepszego sposobu ponownego renderowania.


16
Byłbym zainteresowany, aby dowiedzieć się, dlaczego to głosowanie? Uderzam się w głowę, próbując przekonać czytniki ekranu do reagowania na alerty o ariach i jest to jedyna technika, którą znalazłem, która działa niezawodnie. Jeśli masz coś w interfejsie użytkownika, które generuje ten sam alert za każdym razem, gdy zostanie kliknięte, domyślnie zareaguj nie renderuje DOM, więc czytnik ekranu nie ogłasza zmiany. Ustawienie unikalnego klucza sprawia, że ​​działa. Być może opinia była spowodowana tym, że wciąż wiąże się z ustawieniem stanu. Ale wymuszenie ponownego renderowania do DOM przez ustawienie klucza jest złote!
Martin Bayly,

2
Bardzo podobała mi się ta odpowiedź, ponieważ - 1: odradza się użycie forceupdate (), a 2: ten sposób jest bardzo pomocny dla komponentów innych firm, które zainstalowałeś za pomocą npm, co oznacza, że ​​nie masz własnych komponentów. Np. React-resizable-and-moveable to zewnętrzny komponent, którego używam, ale nie reaguje on na mój stan zestawu komponentów. to świetne rozwiązanie.
Varand Pezeshkian

81
To jest hack i nadużycie key. Po pierwsze, jego zamiar jest niejasny. Czytelnik twojego kodu będzie musiał ciężko pracować, aby zrozumieć, dlaczego używasz w keyten sposób. Po drugie, nie jest to bardziej czyste niż forceUpdate. Reakcja „czysta” oznacza, że ​​wizualna prezentacja twojego komponentu jest w 100% zależna od jego stanu, więc jeśli zmienisz dowolny stan, zostanie zaktualizowany. Jeśli jednak masz jakieś głęboko zagnieżdżone obiekty (scenariusz forceUpdatedokumentuje powód, aby z nich skorzystać), to użycie forceUpdatewyjaśnia. Po trzecie, Math.random()jest… losowy. Teoretycznie mógłby wygenerować tę samą liczbę losową.
atomkirk

8
@xtraSimplicity Nie mogę się zgodzić, że jest to zgodne ze sposobem działania React. forceUpdatejest sposobem React na zrobienie tego.
Rob Grant,

3
@Robert Grant, patrząc wstecz, zgadzam się. Dodatkowa złożoność naprawdę nie jest tego warta.
XtraSimplicity

80

W rzeczywistości forceUpdate()jest to jedyne prawidłowe rozwiązanie, które setState()może nie wyzwalać ponownego renderowania, jeśli zaimplementowana zostanie dodatkowa logika shouldComponentUpdate()lub gdy po prostu wróci false.

wymusić aktualizację()

Wywołanie forceUpdate()spowoduje wywołanie render()komponentu, pomijając shouldComponentUpdate(). więcej...

setState ()

setState()zawsze wyzwala ponowne renderowanie, chyba że logika renderowania warunkowego jest zaimplementowana w shouldComponentUpdate(). więcej...


forceUpdate() może zostać wywołany z twojego komponentu przez this.forceUpdate()


Haki: Jak zmusić komponent do ponownego renderowania za pomocą haków w React?


BTW: Czy mutujesz stan, czy zagnieżdżone właściwości nie propagują się?


1
jedną ciekawą rzeczą do odnotowania jest to, że przydziały stanu poza setState, takie jak this.state.foo = „bar” nie uruchomią metody cyklu życia renderowania
lfender6445,

4
@ lfender6445 Przypisywanie stanu bezpośrednio this.statepoza konstruktorem powinno również generować błąd. Być może nie uczynił tego w 2016 r .; ale jestem pewien, że teraz to robi.
Tyler

Dodałem kilka linków do obejścia bezpośrednich zadań stanowych.
Qwerty

36

Unikałem forceUpdate, wykonując następujące czynności

ŹLE SPOSÓB : nie używaj indeksu jako klucza

this.state.rows.map((item, index) =>
   <MyComponent cell={item} key={index} />
)

PRAWIDŁOWY SPOSÓB : Użyj identyfikatora danych jako klucza, może to być jakiś przewodnik itp

this.state.rows.map((item) =>
   <MyComponent item={item} key={item.id} />
)

więc dzięki takiemu ulepszeniu kodu twój komponent będzie UNIKALNY i będzie renderowany w naturalny sposób


this.state.rows.map((item) => <MyComponent item={item} key={item.id} /> )
Tal

Dziękuję bardzo za popychanie mnie we właściwym kierunku. Używanie indeksu jako klucza było rzeczywiście moim problemem.
RoiEX

Aby uzasadnić mój głos negatywny, mimo że dobrą praktyką jest stosowanie tego podejścia, odpowiedź ta nie jest związana z pytaniem.
micnic

34

Jeśli chcesz, aby komunikowały się dwa komponenty React, które nie są powiązane relacją (rodzic-dziecko), wskazane jest użycie Flux lub podobnych architektur.

To, co chcesz zrobić, to nasłuchiwać zmian w obserwowalnym składniku komponentów , który przechowuje model i jego interfejs, i zapisywać dane, które powodują zmianę renderowania jak statew MyComponent. Gdy sklep wypycha nowe dane, zmieniasz stan swojego komponentu, co automatycznie uruchamia renderowanie.

Zwykle powinieneś unikać używania forceUpdate(). Z dokumentacji:

Zwykle powinieneś starać się unikać wszelkich zastosowań forceUpdate () i czytać tylko z this.props i this.state w render (). Dzięki temu Twoja aplikacja jest znacznie prostsza i wydajniejsza


2
Jaki jest status pamięci stanu elementu? Jeśli mam pięć składników na stronie i wszystkie nasłuchują w jednym sklepie, czy mam dane pięć razy w pamięci, czy są to odwołania? I czy wszyscy ci słuchacze nie sumują się szybko? Dlaczego lepiej „spływać” niż przekazywać dane do celu?
AJFarkas,

5
W rzeczywistości zaleca się przekazywanie danych sklepu do rekwizytów komponentu i używanie stanu komponentu tylko do takich rzeczy, jak stan przewijania i inne drobiazgi specyficzne dla interfejsu użytkownika. Jeśli używasz redux (polecam), możesz użyć funkcji connect z, react-reduxaby automatycznie mapować stan sklepu na rekwizyty komponentowe w razie potrzeby na podstawie dostarczonej funkcji mapowania.
Stijn de Witt

1
@AJFarkas stan zostałby przypisany do danych sklepu, które i tak są tylko wskaźnikiem, więc pamięć nie stanowi problemu, chyba że klonujesz.
Jason Sebring

4
„forceUpdate () należy zawsze unikać” jest niepoprawne. Dokumentacja wyraźnie mówi: „Zwykle powinieneś unikać wszelkich zastosowań forceUpdate ()”. Istnieją ważne przypadki użyciaforceUpdate
AJP

2
@AJP masz całkowitą rację, to było osobiste uprzedzenie :) Zredagowałem odpowiedź.
gcedo

18

użyj haków lub wybierz HOC

Korzystając z haków lub wzorca HOC (komponentu wyższego rzędu) , możesz mieć automatyczne aktualizacje po zmianie sklepów. Jest to bardzo lekkie podejście bez ram.

useStore Hooks sposób obsługi aktualizacji sklepu

interface ISimpleStore {
  on: (ev: string, fn: () => void) => void;
  off: (ev: string, fn: () => void) => void;
}

export default function useStore<T extends ISimpleStore>(store: T) {
  const [storeState, setStoreState] = useState({store});
  useEffect(() => {
    const onChange = () => {
      setStoreState({store});
    }
    store.on('change', onChange);
    return () => {
      store.off('change', onChange);
    }
  }, []);
  return storeState.store;
}

withStores HOC obsługuje aktualizacje sklepu

export default function (...stores: SimpleStore[]) {
  return function (WrappedComponent: React.ComponentType<any>) {
    return class WithStore extends PureComponent<{}, {lastUpdated: number}> {
      constructor(props: React.ComponentProps<any>) {
        super(props);
        this.state = {
          lastUpdated: Date.now(),
        };
        this.stores = stores;
      }

      private stores?: SimpleStore[];

      private onChange = () => {
        this.setState({lastUpdated: Date.now()});
      };

      componentDidMount = () => {
        this.stores &&
          this.stores.forEach((store) => {
            // each store has a common change event to subscribe to
            store.on('change', this.onChange);
          });
      };

      componentWillUnmount = () => {
        this.stores &&
          this.stores.forEach((store) => {
            store.off('change', this.onChange);
          });
      };

      render() {
        return (
          <WrappedComponent
            lastUpdated={this.state.lastUpdated}
            {...this.props}
          />
        );
      }
    };
  };
}

Klasa SimpleStore

import AsyncStorage from '@react-native-community/async-storage';
import ee, {Emitter} from 'event-emitter';

interface SimpleStoreArgs {
  key?: string;
  defaultState?: {[key: string]: any};
}

export default class SimpleStore {
  constructor({key, defaultState}: SimpleStoreArgs) {
    if (key) {
      this.key = key;
      // hydrate here if you want w/ localState or AsyncStorage
    }
    if (defaultState) {
      this._state = {...defaultState, loaded: false};
    } else {
      this._state = {loaded: true};
    }
  }
  protected key: string = '';
  protected _state: {[key: string]: any} = {};
  protected eventEmitter: Emitter = ee({});
  public setState(newState: {[key: string]: any}) {
    this._state = {...this._state, ...newState};
    this.eventEmitter.emit('change');
    if (this.key) {
      // store on client w/ localState or AsyncStorage
    }
  }
  public get state() {
    return this._state;
  }
  public on(ev: string, fn:() => void) {
    this.eventEmitter.on(ev, fn);
  }
  public off(ev: string, fn:() => void) {
    this.eventEmitter.off(ev, fn);
  }
  public get loaded(): boolean {
    return !!this._state.loaded;
  }
}

Jak używać

W przypadku haków:

// use inside function like so
const someState = useStore(myStore);
someState.myProp = 'something';

W przypadku HOC:

// inside your code get/set your store and stuff just updates
const val = myStore.myProp;
myOtherStore.myProp = 'something';
// return your wrapped component like so
export default withStores(myStore)(MyComponent);

UPEWNIJ SIĘ, że możesz eksportować swoje sklepy jako singleton, aby skorzystać z globalnej zmiany:

class MyStore extends SimpleStore {
  public get someProp() {
    return this._state.someProp || '';
  }
  public set someProp(value: string) {
    this.setState({...this._state, someProp: value});
  }
}
// this is a singleton
const myStore = new MyStore();
export {myStore};

To podejście jest dość proste i działa dla mnie. Pracuję również w dużych zespołach, używam Redux i MobX i uważam, że są one również dobre, ale po prostu dużo bojlera. Po prostu osobiście podoba mi się moje własne podejście, ponieważ zawsze nienawidziłem dużo kodu za coś, co może być proste, kiedy jest to potrzebne.


2
Myślę, że jest literówka w swojej klasie przykład Store w sposobie aktualizacji mającej pisać pierwszą linię metody w następujący sposób: this._data = {...this._data, ...newData}.
Norbert,

2
Reakcja zniechęca do dziedziczenia na korzyść kompozycji. reagjs.org/docs/composition-vs-inheritance.html
Fred

1
Zastanawiam się tylko nad klarownością / czytelnością, w jaki sposób coud this.setState (this.state) może być lepszy niż this.forceUpdate ()?
Zoman

17

Tak więc myślę, że moje pytanie brzmi: czy komponenty React muszą mieć stan, aby móc ponownie wysłać? Czy istnieje sposób zmuszenia komponentu do aktualizacji na żądanie bez zmiany stanu?

Inne odpowiedzi próbowały zilustrować, jak możesz, ale chodzi o to, że nie powinieneś . Nawet hacke rozwiązanie zmiany klucza nie ma sensu. Potęgą React jest rezygnacja z ręcznego zarządzania czasem, gdy coś powinno się renderować, a zamiast tego skupienie się na tym, jak coś powinno być mapowane na danych wejściowych. Następnie dostarcz strumień wejściowy.

Jeśli musisz ręcznie wymusić ponowne renderowanie, prawie na pewno nie robisz czegoś dobrze.


@ art-solopov, do jakiego problemu się odnosisz? Które dokumenty je prezentują? Zakładając, że masz na myśli zagnieżdżone obiekty w stanie, odpowiedzią jest użycie innej struktury do przechowywania twojego stanu. To wyraźnie nieoptymalny sposób obsługi stanu w React. Nie powinieneś także zarządzać stanem osobno. Tracisz jedną z największych zalet React, jeśli nie pracujesz z systemem zarządzania stanem. Ręczne zarządzanie aktualizacjami jest anty-wzorcem.
Kyle Baker

Czy możesz sprawdzić to pytanie stackoverflow.com/questions/61277292/... ?
HuLu ViCa

4

Możesz to zrobić na kilka sposobów:

1. Użyj forceUpdate()metody:

Podczas korzystania z tej forceUpdate()metody mogą wystąpić pewne usterki . Jednym z przykładów jest to, że ignoruje shouldComponentUpdate()metodę i ponownie renderuje widok bez względu na to, czy shouldComponentUpdate()zwraca false. Z tego powodu należy w miarę możliwości unikać stosowania forceUpdate ().

2. Przekazanie this.state do setState()metody

Poniższy wiersz kodu rozwiązuje problem z poprzednim przykładem:

this.setState(this.state);

Naprawdę wszystko, co to robi, to zastąpienie bieżącego stanu bieżącym stanem, który uruchamia ponowne renderowanie. To wciąż niekoniecznie najlepszy sposób na robienie rzeczy, ale eliminuje niektóre usterki, które możesz napotkać za pomocą metody forceUpdate ().


2
Ponieważ setState jest podzielony na partie, prawdopodobnie bezpieczniej jest zrobić:this.setState(prevState => prevState);
Mark Galloway,

1
Nie bardzo wiem, dlaczego to jest „usterka”. Nazwa metody („forceUpdate”) nie może być jaśniejsza: zawsze wymusz aktualizację.
Zoman

4

Istnieje kilka sposobów ponownego wysłania komponentu:

Najprostszym rozwiązaniem jest użycie metody forceUpdate ():

this.forceUpdate()

Jeszcze jednym rozwiązaniem jest utworzenie nieużywanego klucza w stanie (nonUsedKey) i wywołanie funkcji setState z aktualizacją tego nonUsedKey:

this.setState({ nonUsedKey: Date.now() } );

Lub przepisz cały aktualny stan:

this.setState(this.state);

Zmiana rekwizytów zapewnia również ponowne wysyłanie komponentów.


3

Dla kompletności możesz to również osiągnąć w elementach funkcjonalnych:

const [, updateState] = useState();
const forceUpdate = useCallback(() => updateState({}), []);
// ...
forceUpdate();

Lub jako hak wielokrotnego użytku:

const useForceUpdate = () => {
  const [, updateState] = useState();
  return useCallback(() => updateState({}), []);
}
// const forceUpdate = useForceUpdate();

Zobacz: https://stackoverflow.com/a/53215514/2692307

Należy pamiętać, że stosowanie mechanizmu aktualizacji siły jest nadal złą praktyką, ponieważ jest sprzeczne z mentalnością reagowania, dlatego należy go w miarę możliwości unikać.


2

Możemy użyć this.forceUpdate () jak poniżej.

       class MyComponent extends React.Component {



      handleButtonClick = ()=>{
          this.forceUpdate();
     }


 render() {

   return (
     <div>
      {Math.random()}
        <button  onClick={this.handleButtonClick}>
        Click me
        </button>
     </div>
    )
  }
}

 ReactDOM.render(<MyComponent /> , mountNode);

Część Element „Math.random” w DOM jest aktualizowana tylko wtedy, gdy używasz setState do ponownego renderowania komponentu.

Wszystkie odpowiedzi tutaj są poprawne i stanowią uzupełnienie pytania dla zrozumienia. Wiemy, że ponowne renderowanie komponentu bez użycia setState ({}) odbywa się za pomocą forceUpdate ().

Powyższy kod działa z setState jak poniżej.

 class MyComponent extends React.Component {



             handleButtonClick = ()=>{
                this.setState({ });
              }


        render() {
         return (
  <div>
    {Math.random()}
    <button  onClick={this.handleButtonClick}>
      Click me
    </button>
  </div>
)
  }
 }

ReactDOM.render(<MyComponent /> , mountNode);

1

Kolejna odpowiedź na kopię zaakceptowanej odpowiedzi :-)

React odradza korzystanie z forceUpdate() ponieważ generalnie mają bardzo „to jest jedyny sposób na to” podejście do programowania funkcjonalnego. W wielu przypadkach jest to w porządku, ale wielu programistów React ma tło OO, a przy takim podejściu słuchanie obserwowalnego obiektu jest całkowicie w porządku.

A jeśli to zrobisz, prawdopodobnie wiesz, że MUSISZ ponownie renderować, gdy możliwe do zaobserwowania „pożary”, i dlatego powinieneś użyć, forceUpdate()a tak naprawdę to plusshouldComponentUpdate() NIE jest tutaj zaangażowany.

Narzędzia takie jak MobX, które przyjmują podejście OO, faktycznie robią to pod powierzchnią (faktycznie wywołania MobX render()bezpośrednio)


0

Uważam, że najlepiej jest unikać forceUpdate (). Jednym ze sposobów wymuszenia ponownego renderowania jest dodanie zależności render () od tymczasowej zmiennej zewnętrznej i zmiana wartości tej zmiennej w razie potrzeby.

Oto przykład kodu:

class Example extends Component{
   constructor(props){
      this.state = {temp:0};

      this.forceChange = this.forceChange.bind(this);
   }

   forceChange(){
      this.setState(prevState => ({
          temp: prevState.temp++
      })); 
   }

   render(){
      return(
         <div>{this.state.temp &&
             <div>
                  ... add code here ...
             </div>}
         </div>
      )
   }
}

Wywołaj this.forceChange (), gdy musisz wymusić ponowne renderowanie.


0

ES6 - podaję przykład, który był dla mnie pomocny:

W „krótkiej instrukcji if” możesz przekazać pustą funkcję w następujący sposób:

isReady ? ()=>{} : onClick

To wydaje się być najkrótszym podejściem.

()=>{}



0

Innym sposobem jest wywołanie setState, I zachować stan:

this.setState(prevState=>({...prevState}));


0

forceUpdate (), ale za każdym razem, gdy słyszę, że ktoś o tym mówi, jest śledzone, że nigdy nie powinieneś tego używać.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.