In React, qual è la differenza tra onChange e onInput?


90

Ho provato a cercare una risposta a questo, ma la maggior parte di loro è al di fuori del contesto di React, dove si onChangeinnesca su sfocatura.

Durante l'esecuzione di vari test, non riesco a dire in che modo questi due eventi sono diversi (quando applicati a un'area di testo). Qualcuno può far luce su questo?


1
Ho modificato il mio post per essere più chiaro. Stavo parlando specificamente dell'area di testo, non dei pulsanti di opzione o delle caselle di controllo.
ffxsam

È abbastanza falso, React non è solo JS. E gli eventi si comportano in modo leggermente diverso in alcuni casi (come onChange). E no, incollare il testo in un'area di testo (in React) attiva sia onChangee onInput. Sentiti libero di provare in un violino e vedrai.
ffxsam

Per <input> e <textarea>, onChange sostituisce - e dovrebbe generalmente essere usato al posto - del gestore di eventi oninput integrato del DOM.
Roko C. Buljan

Suppongo che onChange sia la scommessa più sicura. Ho anche provato a modificare in modo programmatico il valore della textarea, pensando che forse si onChangesarebbe attivato e onInputnon si sarebbe attivato , ma entrambi si attivano.
ffxsam

Sì, ora dopo aver esaminato un po 'di React Docs, vedo che React fa alcune cose come jQuery, normalizza gli eventi e sì. onChange sembra un modo preferito. E sì. React non è altro che JS. Non c'è magia speciale. Solo regole.
Roko C. Buljan

Risposte:


81

Sembra che non ci sia una reale differenza

React, per qualche motivo, collega i listener per all'evento Component.onChangeDOM element.oninput. Vedere la nota nella documentazione sui moduli:

React docs - Moduli

Ci sono più persone che sono sorprese da questo comportamento. Per maggiori dettagli, fai riferimento a questo problema nel tracker dei problemi di React:

Documenta come onChange di React si riferisce a onInput # 3964

Citazione dai commenti su quel problema:

Non capisco perché React abbia scelto di fare in modo che onChange si comporti come fa onInput. Per quanto ne so, non abbiamo modo di recuperare il vecchio comportamento di onChange. I documenti affermano che è un "nome improprio" ma non lo è davvero, si attiva quando c'è un cambiamento, solo non finché l'input non perde il focus.

Per la convalida, a volte non vogliamo mostrare errori di convalida finché non hanno terminato di digitare. O forse semplicemente non vogliamo un re-rendering su ogni battitura. Ora l'unico modo per farlo è con onBlur, ma ora dobbiamo anche controllare che il valore sia cambiato manualmente.

Non è un grosso problema, ma mi sembra che React abbia gettato via un evento utile e abbia deviato dal comportamento standard quando c'era già un evento che lo fa.

Sono d'accordo al 100% con il commento ... Ma immagino che cambiarlo ora porterebbe più problemi di quanti ne risolva poiché era già stato scritto così tanto codice che si basa su questo comportamento.

React non fa parte della raccolta Web API ufficiale

Anche se React è costruito su JS e ha visto un enorme tasso di adozione, poiché una tecnologia React esiste per nascondere un sacco di funzionalità sotto la sua (piuttosto piccola) API. Una volta che l'area in cui questo è ovvio è nel sistema degli eventi, dove c'è molto da fare sotto la superficie che in realtà è radicalmente diverso dal sistema di eventi DOM standard. Non solo in termini di quali eventi fanno cosa, ma anche in termini di quando i dati possono persistere in quale fase della gestione dell'evento. Puoi leggere altro a questo proposito qui:

React Event System


1
Il paragrafo finale è fuorviante / falso.
rounce

1
React non è un framework (dove fornisce routing, persistenza, gestione I / O di rete, ecc.?), È una libreria che fornisce l'astrazione principale per manipolare alberi di visualizzazione tramite backend specifici della piattaforma (react-dom, react-native, eccetera.).
rounce

7
Wow ok. Sono un po 'd'accordo che sia più una libreria che un framework, ma chiamare il paragrafo fuorviante / falso per questo ?? Non sono inoltre d'accordo con l'idea che un framework debba fornire tutti gli aspetti di un'applicazione web ... Ci sono framework di routing per esempio, o cose come redux che è un framework di gestione dello stato. Nella mia mente, un framework ti consente di riempire pezzi di una macchina funzionante. Nel caso di Redux, inserisci i riduttori. Nel caso di Express, inserisci i gestori delle richieste e il middleware. Ecc. Ma la distinzione è a dir poco grigia.
Stijn de Witt

4
completamente d'accordo. discutere sulla distinzione tra libreria e framework è davvero una perdita di tempo. dipende solo dal livello di astrazione a cui stai lavorando.
swyx

1
@chadsteele Grazie amico, è bello sentire che ti ha aiutato
Stijn de Witt

23

Non c'è differenza

React non ha il comportamento dell'evento predefinito "onChange". Il 'onChange' che vediamo in react ha il comportamento dell'evento 'onInput' di default. Quindi, per rispondere alla tua domanda, non c'è differenza in entrambi nella reazione. Ho sollevato un problema su GitHub riguardo lo stesso e questo è ciò che hanno da dire al riguardo:

Penso che al momento in cui è stata presa questa decisione (~ 4 anni fa?), OnInput non funzionava in modo coerente tra i browser e creava confusione per le persone che accedevano al Web da altre piattaforme, poiché si aspettavano che l'evento di "modifica" fuoco su ogni cambiamento. In caso di React, è un problema più grande perché se non riesci a gestire il cambiamento abbastanza presto, gli input controllati non si aggiornano mai, portando le persone a pensare che React non funzioni. Quindi il team ha deciso di chiamarlo onChange.

In retrospettiva, sarebbe stata un'idea migliore eseguire il polyfill su Input e mantenere il suo nome piuttosto che modificare il comportamento di un altro evento. Ma quella nave ha navigato molto tempo fa. Potremmo rivedere questa decisione in futuro, ma ti incoraggio solo a trattarla come una stranezza di React DOM (a cui ti abituerai abbastanza rapidamente).

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

Anche questo articolo fornirà maggiori informazioni. Come soluzione alternativa alla mancanza di "onChange" predefinito, l'articolo suggerisce di ascoltare l'evento "onBlur".

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


Mi sembra di essermi imbattuto in una differenza. OnChange di React non si attiva quando si seleziona e si sostituisce un personaggio con lo stesso carattere, si innesca onInput.
Per Enström

3

Recentemente ho ricevuto un bug in cui onChangenon consentiva il copia e incolla nel campo di input su IE11. Considerando che l' onInputevento consentirebbe quel comportamento. Non sono riuscito a trovare alcuna documentazione che descriva ciò nei documenti, ma ciò mostra che c'è una differenza tra i due (prevista o meno).


2

Come puoi vedere in vari commenti qui, React tratta onChange e onInput allo stesso modo e così, piuttosto che discutere i meriti di questa decisione. Ecco la soluzione.

Usa onBlur quando non vuoi elaborare le modifiche dell'utente finché non sono terminate. :)


1

Per chiunque si sia imbattuto in questo problema alla ricerca di un modo per ascoltare l'effettivo changeevento basato su DOM , ecco come l'ho fatto (scritto in 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} />;
    }
}

Per favore fatemi sapere se trovate modi per migliorare questo approccio o se incontrate problemi con esso. Diversamente blur, ilchange evento viene attivato anche quando l'utente preme Invio e viene attivato solo se il valore è effettivamente cambiato.

Sto ancora acquisendo esperienza con questo CustomInputcomponente. Ad esempio, le caselle di controllo si comportano in modo strano. Devo invertire event.target.checkedil onChangegestore mentre si passa il valore alla casella di controllo con checkedo eliminare questa inversione quando si passa il valore alla casella di controllo con, defaultCheckedma questo interrompe che diverse caselle di controllo che rappresentano lo stesso stato in punti diversi della pagina rimangono sincronizzate . (In entrambi i casi, non ho passato un onInputgestore alle CustomInputcaselle di controllo per.)


0

Una differenza sembra essere che onChangenon viene attivato quando si seleziona e si sostituisce un personaggio con lo stesso carattere, mentre lo onInputè.

Vedi questo sandbox: https://codesandbox.io/s/react-onchange-vs-oninput-coggf?file=/src/App.js

  • Digita "A" nel campo, quindi seleziona tutto e digita "B". Questo attiverà 4 eventi, 2 onChangee 2 onInput.
  • Ora seleziona tutto e digita di nuovo "B", questo finché non si attiva un nuovo onInputevento, ma no onChange.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.