Menu

Zdarzenia w React: onClick, onChange, onSubmit i inne

Zdarzenia w React to propsy takie jak onClick i onChange, które przyjmują funkcję, a React wywołuje ją z obiektem zdarzenia, gdy użytkownik coś zrobi. Dowiedz się, jak przekazać handler zamiast go wywołać, przekazywać argumenty, odczytywać e.target.value i e.key, blokować przeładowanie formularza i zatrzymywać propagację.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

React obsługuje zdarzenia przez propsy nazwane od zdarzenia w camelCase, takie jak onClick, onChange i onSubmit. Przekazujesz funkcję, a React wywołuje ją z obiektem zdarzenia, gdy użytkownik kliknie, pisze albo wyśle formularz.

Każde kliknięcie uruchamia handleClick, który aktualizuje licznik i wypisuje log w konsoli pod podglądem. Wypróbuj onDoubleClick zamiast onClick: teraz liczy się tylko podwójne kliknięcie.

Przekaż funkcję, nie wywołuj jej

Prop przyjmuje funkcję, a React wywołuje ją później. Bardzo częstym błędem jest dodanie nawiasów, co wywołuje funkcję od razu, podczas renderowania, i oddaje Reactowi zamiast niej jej wartość zwracaną.

Konsola pokazuje "Hi, during render", zanim czegokolwiek dotkniesz: React uruchomił sayHi podczas renderowania pierwszego przycisku, a ponieważ sayHi zwraca undefined, ten przycisk w ogóle nie ma handlera. Kliknięcie Wrong nic nie robi. Kliknięcie Right wypisuje "Hi, Ada", bo funkcja strzałkowa uruchamia się dopiero po kliknięciu.

Strzałka to też sposób na przekazywanie argumentów. onClick={() => removeItem(item.id)} tworzy małą funkcję dla każdego elementu, a ta funkcja wywołuje twoją z właściwym ID. Jeśli handler nie przyjmuje argumentów, przekaż go po nazwie: onClick={handleClick}.

Z setterem stanu ten błąd jest jeszcze gorszy: onClick={setCount(count + 1)} ustawia stan podczas renderowania, co renderuje ponownie, co znowu ustawia stan, a React zatrzymuje się z komunikatem "Too many re-renders".

Obiekt zdarzenia

React przekazuje każdemu handlerowi jeden argument, obiekt zdarzenia. Ma on te same właściwości co zdarzenie przeglądarki: e.target to element, na którym zdarzenie wystąpiło, e.key to naciśnięty klawisz, e.preventDefault() anuluje domyślną akcję przeglądarki. React opakowuje natywne zdarzenie w coś, co nazywa zdarzeniem syntetycznym, więc działa ono tak samo w każdej przeglądarce; oryginał jest w e.nativeEvent, gdybyś go kiedyś potrzebował.

Najczęściej używasz dwóch: e.target.value w onChange i e.key w onKeyDown.

Wpisz hooks i naciśnij Enter: tag zostaje dodany, a pole się czyści. Konsola wypisuje każdy klawisz, w tym Shift, Backspace i Enter, pod nazwami z e.key. Naciśnij Escape w połowie słowa, żeby je odrzucić.

onChange w React uruchamia się przy każdym naciśnięciu klawisza. W zwykłym HTML zdarzenie change na polu tekstowym uruchamia się dopiero, gdy pole traci fokus, więc to celowa różnica: pozwala polu i stanowi iść krok w krok, litera po literze. Pola wyboru dają e.target.checked zamiast value. Strona o formularzach omawia każdy typ pola.

Formularze i preventDefault

Gdy formularz zostaje wysłany, domyślną akcją przeglądarki jest wysłanie go i załadowanie nowej strony. W aplikacji React prawie zawsze chcesz sam obsłużyć dane, więc handler wysyłania zaczyna się od e.preventDefault().

Umieść onSubmit na <form>, a nie onClick na przycisku: wtedy naciśnięcie Enter w polu też wysyła formularz, a własne sprawdzenia przeglądarki (tu required i type="email") wykonują się najpierw. Usuń linię e.preventDefault() i wyślij ponownie: prawdziwa strona przeszłaby teraz na nową stronę i zgubiła podziękowanie. Podgląd to blokuje i zamiast tego pokazuje, co wysłałby formularz, email= bez wartości, bo setEmail('') wyczyściło już pole, zanim formularz został odczytany.

React 19 pozwala też przekazać funkcję do <form action={fn}>, która dostaje dane formularza i sama resetuje niekontrolowane pola. Strona o formularzach pokazuje oba style.

Propagacja i stopPropagation

Większość zdarzeń propaguje się w górę (bubbling): po wykonaniu na klikniętym elemencie wykonują się na jego rodzicu, potem na rodzicu rodzica, aż do samej góry. Handlery Reacta zachowują tę samą kolejność. Dlatego kliknięcie przycisku wewnątrz klikalnej karty liczy się też jako kliknięcie karty.

Kliknij Bubbles up, a konsola wypisze przycisk, potem wewnętrzny panel, potem zewnętrzną kartę. Kliknij Stops here, a wypisze się tylko przycisk: e.stopPropagation() kończy wspinaczkę. Kliknięcie tekstu samego wewnętrznego panelu wypisuje panel i kartę.

Używaj stopPropagation oszczędnie. Częsty uzasadniony przypadek to przycisk usuwania w klikalnym wierszu listy, gdzie kliknięcie usuwania nie powinno też otwierać wiersza. Jeśli rodzic musi wiedzieć, czy kliknięcie przyszło od dziecka, sprawdź e.target zamiast zatrzymywać zdarzenie. Żeby uruchomić handler w drodze w dół, zanim zdarzenie zobaczą dzieci, React oferuje wersje dla fazy przechwytywania, takie jak onClickCapture.

preventDefault i stopPropagation to różne narzędzia. Pierwsze anuluje to, co zrobiłaby przeglądarka (przejście po linku, wysłanie formularza, zaznaczenie pola wyboru). Drugie sprawia, że inne handlery nie dowiedzą się o zdarzeniu. Wywołanie jednego nie robi tego, co drugie.

Inne popularne zdarzenia

Ten sam wzorzec obejmuje każde zdarzenie, które obsługuje React. Kilka, których będziesz często używać:

  • onFocus i onBlur uruchamiają się, gdy pole zyskuje i traci fokus, przydatne do pokazywania walidacji, gdy użytkownik opuści pole.
  • onMouseEnter i onMouseLeave uruchamiają się, gdy wskaźnik wchodzi na element i z niego schodzi. W odróżnieniu od większości zdarzeń nie propagują się w górę, więc przesunięcie wskaźnika z rodzica na jego dziecko nie uruchamia ponownie onMouseEnter rodzica.
  • onPointerDown, onPointerMove i onPointerUp działają tak samo dla myszy, dotyku i pióra, dlatego lepiej sprawdzają się przy przeciąganiu.
  • onScroll uruchamia się, gdy element jest przewijany. W React nie propaguje się w górę.

Każdy handler dostaje obiekt zdarzenia z właściwościami, które mają dla niego sens: e.clientX dla zdarzeń wskaźnika, e.key dla zdarzeń klawiatury, e.target dla wszystkich.

Przekazywanie handlerów jako propsów

Komponenty mogą przyjmować handlery od rodzica jak każdy inny prop. Nazywaj je onSomething od tego, co się stało, a funkcję, która to obsługuje, handleSomething. To odzwierciedla wbudowane zdarzenia i od razu pokazuje, które propsy są callbackami.

Stepper nie jest właścicielem liczby; zgłasza kliknięcia, a rodzic decyduje, co oznaczają. Zmień handleDecrement tak, żeby zatrzymywał się na 1 zamiast 0, a stepper się dostosuje bez edytowania go. Trzymanie stanu w rodzicu i przekazywanie handlerów w dół to wzorzec opisany w podnoszeniu stanu.

Własne propsy handlerów to tylko nazwy. onIncrement na twoim komponencie nic nie robi, dopóki komponent nie przekaże go do onClick prawdziwego elementu, a możesz mu dać dowolne argumenty, na przykład onSelect(item.id).

Najczęściej zadawane pytania

Jak przekazać parametr do handlera onClick?

Owiń wywołanie w funkcję strzałkową: onClick={() => deleteItem(item.id)}. To strzałkę React wywołuje po kliknięciu, a ona wywołuje twoją funkcję z argumentem.

Dlaczego mój onClick uruchamia się przy ładowaniu strony?

Wywołałeś funkcję zamiast ją przekazać. onClick={handleClick()} uruchamia handleClick podczas renderowania i przekazuje wartość, którą zwraca. Napisz onClick={handleClick} albo onClick={() => handleClick(id)}.

Czym różni się onChange w React i w HTML?

W HTML zdarzenie change na polu tekstowym uruchamia się, gdy pole traci fokus. onChange w React uruchamia się przy każdym naciśnięciu klawisza, jak natywne zdarzenie input, więc stan może podążać za tekstem w trakcie pisania.

Jak w React zablokować przeładowanie strony przez formularz?

Wywołaj e.preventDefault() na początku handlera onSubmit. Umieść handler na <form>, a nie na przycisku wysyłania, żeby naciśnięcie Enter w polu też wysyłało formularz.

Co to jest zdarzenie syntetyczne w React?

To obiekt zdarzenia, który React przekazuje twoim handlerom. Opakowuje natywne zdarzenie przeglądarki tymi samymi właściwościami i metodami (target, key, preventDefault(), stopPropagation()) i działa tak samo we wszystkich przeglądarkach. Oryginał jest dostępny jako e.nativeEvent.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ