En React, ¿cuál es la diferencia entre onChange y onInput?

86

Intenté buscar una respuesta a esto, pero la mayoría de ellos están fuera del contexto de React, donde se onChangedesencadena al desenfoque.

Al realizar varias pruebas, parece que no puedo decir en qué se diferencian estos dos eventos (cuando se aplican a un área de texto). ¿Alguien puede arrojar algo de luz sobre esto?

ffxsam
fuente
1
Edité mi publicación para que sea más clara. Estaba hablando específicamente de textarea, no de botones de radio o casillas de verificación.
ffxsam
Eso es bastante falso, React no es solo JS. Y los eventos se comportan de manera ligeramente diferente en algunos casos (como onChange). Y no, pegar texto en un área de texto (en React) activa tanto onChangey onInput. Siéntase libre de probar en un violín y lo verá.
ffxsam
Para <input> y <textarea>, onChange reemplaza, y generalmente debe usarse en lugar de, el controlador de eventos oninput integrado del DOM.
Roko C. Buljan
Supongo que onChange es la apuesta más segura. Incluso traté de cambiar programáticamente el valor del área de texto, pensando que tal vez onChangese dispararía y onInputno, pero ambos se dispararían.
ffxsam
Sí, ahora, después de revisar un poco de React Docs, veo que React hace bastantes cosas como jQuery, normaliza eventos y sí. onChange parece una forma preferida. Y sí. React no es más que JS. No hay magia especial. Solo reglas.
Roko C. Buljan

Respuestas:

79

Parece que no hay diferencia real

React, por alguna razón, adjunta oyentes Component.onChangeal element.oninputevento DOM . Vea la nota en los documentos sobre formularios:

React docs - Formularios

Hay más personas a las que les sorprende este comportamiento. Para obtener más detalles, consulte este problema en el rastreador de problemas de React:

Documente cómo el onChange de React se relaciona con onInput # 3964

Cita de los comentarios sobre ese tema:

No entiendo por qué React eligió hacer que onChange se comporte como lo hace onInput. Por lo que puedo decir, no tenemos forma de recuperar el antiguo comportamiento de onChange. Los médicos afirman que es un "nombre inapropiado", pero no lo es realmente, se activa cuando hay un cambio, pero no hasta que la entrada también pierde el foco.

Para la validación, a veces no queremos mostrar errores de validación hasta que hayan terminado de escribir. O tal vez simplemente no queremos volver a renderizar con cada pulsación de tecla. Ahora, la única forma de hacerlo es con onBlur, pero ahora también debemos verificar que el valor haya cambiado manualmente.

No es un gran problema, pero me parece que React descartó un evento útil y se desvió del comportamiento estándar cuando ya había un evento que lo hacía.

Estoy 100% de acuerdo con el comentario ... Pero supongo que cambiarlo ahora traerá más problemas de los que resuelve, ya que se había escrito tanto código que se basa en este comportamiento.

React no es parte de la colección oficial de API web

A pesar de que React está construido sobre JS y ha visto una gran tasa de adopción, como tecnología, React existe para ocultar una gran cantidad de funcionalidades bajo su propia API (bastante pequeña). Una vez que el área donde esto es obvio es en el sistema de eventos, donde están sucediendo muchas cosas bajo la superficie que en realidad son radicalmente diferentes del sistema de eventos DOM estándar. No solo en términos de qué eventos hacen qué, sino también en términos de cuándo se permite que los datos persistan en qué etapa del manejo de eventos. Puedes leer mas al respecto aquí:

React Event System

Stijn de Witt
fuente
El párrafo final es engañoso / falso.
rebote el
1
React no es un marco (¿dónde proporciona enrutamiento, persistencia, administración de E / S de red, etc.?), Es una biblioteca que proporciona la abstracción central para manipular árboles de visualización a través de backends específicos de la plataforma (react-dom, react-native, etc.).
2018
7
Wow, esta bién. Estoy de acuerdo en que es más una biblioteca que un marco, pero ¿llamar al párrafo engañoso / falso por eso? También estoy en desacuerdo con la noción de que un marco debería proporcionar todos los aspectos de una aplicación web ... Hay marcos de enrutamiento, por ejemplo, o cosas como redux, que es un marco de gestión estatal. En mi opinión, un marco te permite completar partes de una máquina en funcionamiento. En el caso de Redux, rellenas reductores. En el caso de Express, complete los controladores de solicitudes y el middleware. Etc. Pero la distinción es un área gris por decir lo menos.
Stijn de Witt
4
totalmente de acuerdo. discutir sobre la distinción entre biblioteca y marco es realmente una pérdida de tiempo. solo depende del nivel de abstracción en el que esté trabajando.
swyx
1
@chadsteele Gracias amigo, es bueno saber que te ayudó
Stijn de Witt
21

No hay diferencia

React no tiene el comportamiento del evento predeterminado 'onChange'. El 'onChange' que vemos en react tiene el comportamiento del evento predeterminado 'onInput'. Entonces, para responder a su pregunta, no hay diferencia en la reacción de ambos. He planteado un problema en GitHub con respecto a lo mismo y esto es lo que tienen que decir al respecto:

Creo que en el momento en que se tomó esta decisión (¿~ hace 4 años?), OnInput no funcionaba de manera uniforme entre los navegadores y era confuso para las personas que ingresaban a la web desde otras plataformas, ya que esperaban que el evento de "cambio" fuego en cada cambio. En el caso de React, es un problema mayor porque si no logra manejar el cambio lo suficientemente pronto, las entradas controladas nunca se actualizan, lo que lleva a la gente a pensar que React no funciona. Así que el equipo lo llamó onChange.

En retrospectiva, podría haber sido una mejor idea hacer un polyfill onInput y mantener su nombre en lugar de cambiar el comportamiento de otro evento. Pero ese barco ha zarpado hace mucho tiempo. Es posible que revisemos esta decisión en el futuro, pero le animo a que la trate como una peculiaridad de React DOM (a la que se acostumbrará bastante rápido).

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

Además, este artículo proporcionará más información. Como solución para la falta de 'onChange' predeterminado, el artículo sugiere escuchar el evento 'onBlur'.

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

Nikhil Goyal
fuente
3

Recientemente obtuve un error onChangeque no permitía copiar y pegar en el campo de entrada en IE11. Considerando que el onInputevento permitiría ese comportamiento. No pude encontrar ninguna documentación que describiera esto en los documentos, pero eso muestra que hay una diferencia entre los dos (esperada o no).

Alan Souza
fuente
2

Como puede ver en varios comentarios aquí, React trata onChange y onInput de la misma manera, en lugar de debatir los méritos de esta decisión. Esta es la solución.

Use onBlur cuando no desee procesar las ediciones del usuario hasta que estén listas. :)

chad steele
fuente
1

Para cualquiera que haya tropezado con este problema buscando una forma de escuchar el changeevento real basado en DOM , así es como lo hice (escrito en 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} />;
    }
}

Por favor, avíseme si encuentra formas de mejorar este enfoque o tiene problemas con él. A diferencia de blurlachange evento también se activa cuando el usuario presiona Enter y solo se activa si el valor realmente cambió.

Todavía estoy ganando experiencia con este CustomInputcomponente. Por ejemplo, las casillas de verificación se comportan de forma extraña. Tengo que invertir event.target.checkeden el onChangecontrolador mientras paso el valor a la casilla de verificación con checkedo deshacerme de esta inversión al pasar el valor a la casilla de verificación con, defaultCheckedpero esto rompe que varias casillas de verificación que representan el mismo estado en diferentes lugares de la página se mantienen sincronizadas . (En ambos casos, no pasé un onInputcontrolador a las CustomInputcasillas de verificación for).

Kaspar Etter
fuente