Jaka jest różnica między onChange a onInput w React?

86

Próbowałem znaleźć odpowiedź na to pytanie, ale większość z nich jest poza kontekstem React, gdzie onChangewyzwala się po rozmyciu.

Wykonując różne testy, nie mogę powiedzieć, jak te dwa zdarzenia są różne (po zastosowaniu do obszaru tekstowego). Czy ktoś może rzucić na to trochę światła?

ffxsam
źródło
1
Zredagowałem swój post, aby był bardziej przejrzysty. Mówiłem konkretnie o obszarze tekstowym, a nie o przyciskach opcji lub polach wyboru.
ffxsam
To nieprawda, React to nie tylko JS. W niektórych przypadkach zdarzenia zachowują się nieco inaczej (np. onChange). I nie, wklejenie tekstu w obszarze tekstowym (w Reakcie) wyzwala zarówno onChangei onInput. Zapraszam do testowania na skrzypcach, a zobaczysz.
ffxsam
W przypadku <input> i <textarea> onChange zastępuje - i generalnie powinien być używany zamiast - wbudowany moduł obsługi zdarzeń oninput DOM.
Roko C. Buljan
Przypuszczam, że onChange jest bezpieczniejszym rozwiązaniem. Próbowałem nawet programowo zmienić wartość textarea, myśląc, że może onChangewyzwoli, a onInputnie, ale oba wyzwalają.
ffxsam,
Tak, teraz po przejrzeniu części React Docs widzę, że React robi całkiem sporo rzeczy, takich jak jQuery, normalizuje zdarzenia i tak. onChange wydaje się preferowanym sposobem. I tak. React to nic innego jak JS. Nie ma specjalnej magii. Po prostu zasady.
Roko C. Buljan

Odpowiedzi:

79

Wygląda na to, że nie ma żadnej różnicy

Reaguj, z jakiegoś powodu, dołącza detektory Component.onChangedo element.oninputzdarzenia DOM . Zobacz uwagę w dokumentach na formularzach:

React docs - Formularze

Jest więcej osób, które są zaskoczone tym zachowaniem. Aby uzyskać więcej informacji, zapoznaj się z tym problemem w narzędziu do śledzenia problemów w React:

Udokumentuj, jak reakcja onChange odnosi się do onInput # 3964

Cytuj z komentarzy w tej sprawie:

Nie rozumiem, dlaczego React zdecydował, że onChange zachowuje się tak, jak onInput. O ile wiem, nie mamy możliwości przywrócenia starego zachowania onChange. Dokumenty twierdzą, że jest to „błędna nazwa”, ale tak naprawdę nie jest, uruchamia się, gdy następuje zmiana, ale nie do momentu, gdy dane wejściowe również tracą ostrość.

W celu weryfikacji czasami nie chcemy pokazywać błędów walidacji, dopóki nie zakończą wpisywania. A może po prostu nie chcemy ponownego renderowania po każdym naciśnięciu klawisza. Teraz jedynym sposobem na to jest użycie onBlur, ale teraz musimy również sprawdzić, czy wartość zmieniła się ręcznie.

To nie jest taka wielka sprawa, ale wydaje mi się, że React odrzucił użyteczne wydarzenie i odszedł od standardowego zachowania, gdy już było wydarzenie, które to robi.

Zgadzam się w 100% z komentarzem ... Ale myślę, że zmiana go teraz przyniosłaby więcej problemów niż rozwiązuje, ponieważ napisano już tyle kodu, który opiera się na tym zachowaniu.

React nie jest częścią oficjalnej kolekcji Web API

Mimo że React jest zbudowany na bazie JS i odnotował ogromny współczynnik adaptacji, ponieważ React istnieje technologii, która ukrywa całą masę funkcji pod własnym (dość małym) API. Kiedyś obszar, w którym jest to oczywiste, to system zdarzeń, gdzie pod powierzchnią dzieje się wiele rzeczy, które w rzeczywistości radykalnie różnią się od standardowego systemu zdarzeń DOM. Nie tylko pod względem tego, które zdarzenia robią co, ale także pod względem tego, kiedy dane mogą pozostać na jakim etapie obsługi zdarzenia. Możesz przeczytać więcej na ten temat tutaj:

System reagowania na zdarzenia

Stijn de Witt
źródło
Ostatni akapit wprowadza w błąd / jest nieprawdziwy.
odbędą się
1
React nie jest frameworkiem (gdzie zapewnia routing, trwałość, zarządzanie we / wy sieci itp.?), Jest to biblioteka, która zapewnia podstawową abstrakcję do manipulowania drzewami wyświetlania za pośrednictwem specyficznych dla platformy backendów (react-dom, react-native, itp.).
wystrzelenie
7
Wow ok. W pewnym sensie zgadzam się, że to bardziej biblioteka niż framework, ale z tego powodu nazwać akapit mylącym / nieprawdziwym? Nie zgadzam się również z poglądem, że framework powinien zapewniać wszystkie aspekty aplikacji internetowej ... Istnieją na przykład frameworki routingu lub rzeczy takie jak redux, które jest strukturą zarządzania stanem. Moim zdaniem framework pozwala wypełnić fragmenty działającej maszyny. W przypadku Redux uzupełniasz reduktory. W przypadku Express wypełniasz moduły obsługi żądań i oprogramowanie pośredniczące. Itd. Ale rozróżnienie jest co najmniej szarą strefą.
Stijn de Witt
4
kompletnie się zgadzam. spory o rozróżnienie między biblioteką a frameworkiem to naprawdę strata czasu. zależy tylko od tego, na jakim poziomie abstrakcji pracujesz.
swyx
1
@chadsteele Dzięki kolego, świetnie słyszeć, że ci pomogło
Stijn de Witt
21

Nie ma różnicy

React nie ma zachowania domyślnego zdarzenia „onChange”. „OnChange”, które widzimy w reakcji, zachowuje się jak domyślne zdarzenie „onInput”. Tak więc, odpowiadając na twoje pytanie, nie ma różnicy w reagowaniu obu z nich. Podniosłem problem na GitHubie dotyczący tego samego i oto, co mają do powiedzenia na ten temat:

Myślę, że w czasie, gdy podejmowano tę decyzję (~ 4 lata temu?), OnInput nie działał konsekwentnie między przeglądarkami i był dezorientujący dla osób wchodzących do sieci z innych platform, ponieważ spodziewali się, że wydarzenie „zmiany” strzelać do każdej zmiany. W przypadku React jest to większy problem, ponieważ jeśli nie poradzisz sobie ze zmianą wystarczająco wcześnie, kontrolowane dane wejściowe nigdy się nie aktualizują, co prowadzi do wniosku, że React jest uszkodzony. Zespół zdecydował się więc nazwać to onChange.

Z perspektywy czasu lepszym pomysłem mogłoby być wypełnienie na wejściu i zachowanie nazwy zamiast zmiany zachowania innego zdarzenia. Ale ten statek płynął dawno temu. Być może w przyszłości powrócimy do tej decyzji, ale zachęcam Cię do potraktowania jej jako dziwactwa React DOM (do którego dość szybko się przyzwyczaisz).

https://github.com/facebook/react/issues/9567

Również ten artykuł zapewni więcej informacji. Aby obejść brak domyślnego „onChange”, artykuł sugeruje odsłuchiwanie zdarzenia „onBlur”.

https://www.peterbe.com/plog/onchange-in-reactjs

Nikhil Goyal
źródło
3

Niedawno dostałem błąd, onChangektóry uniemożliwiał kopiowanie i wklejanie w polu wejściowym w IE11. Tymczasem onInputwydarzenie pozwoliłoby na takie zachowanie. Nie mogłem znaleźć żadnej dokumentacji, która opisywałaby to w dokumentach, ale to pokazuje, że istnieje różnica między nimi (oczekiwana lub nie).

Alan Souza
źródło
2

Jak widać w różnych komentarzach tutaj, React traktuje onChange i onInput tak samo, zamiast dyskutować o zaletach tej decyzji. Oto rozwiązanie.

Użyj onBlur, jeśli nie chcesz przetwarzać zmian wprowadzonych przez użytkownika, dopóki nie zostaną zakończone. :)

chad steele
źródło
1

Dla każdego, kto natknął się na ten problem, szukając sposobu na nasłuchiwanie rzeczywistego changezdarzenia opartego na DOM , oto jak to zrobiłem (napisane w TypeScript):

import { Component, createElement, InputHTMLAttributes } from 'react';

export interface CustomInputProps {
    onChange?: (event: Event) => void;
    onInput?: (event: Event) => void;
}

/**
 * This component restores the 'onChange' and 'onInput' behavior of JavaScript.
 *
 * See:
 * - https://reactjs.org/docs/dom-elements.html#onchange
 * - https://github.com/facebook/react/issues/3964
 * - https://github.com/facebook/react/issues/9657
 * - https://github.com/facebook/react/issues/14857
 */
export class CustomInput extends Component<Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'onInput' | 'ref'> & CustomInputProps> {
    private readonly registerCallbacks  = (element: HTMLInputElement | null) => {
        if (element) {
            element.onchange = this.props.onChange ? this.props.onChange : null;
            element.oninput = this.props.onInput ? this.props.onInput : null;
        }
    };

    public render() {
        return <input ref={this.registerCallbacks} {...this.props} onChange={undefined} onInput={undefined} />;
    }
}

Daj mi znać, jeśli zobaczysz sposoby na ulepszenie tego podejścia lub napotkasz z nim problemy. W przeciwieństwie do blurtego changezdarzenie jest również wyzwalane, gdy użytkownik naciśnie klawisz Enter, i jest wyzwalane tylko wtedy, gdy wartość faktycznie uległa zmianie.

Wciąż zdobywam doświadczenie z tym CustomInputelementem. Na przykład pola wyboru zachowują się dziwnie. Muszę odwrócić wartość event.target.checkedw module onChangeobsługi podczas przekazywania wartości do pola wyboru checkedlub pozbyć się tego odwrócenia podczas przekazywania wartości do pola wyboru, defaultCheckedale to zrywa, że ​​kilka pól wyboru reprezentujących ten sam stan w różnych miejscach na stronie pozostaje zsynchronizowanych . (W obu przypadkach nie przekazałem onInputobsługi do pól CustomInputwyboru for.)

Kaspar Etter
źródło