No React, qual é a diferença entre onChange e onInput?

86

Tentei pesquisar uma resposta para isso, mas a maioria delas está fora do contexto de React, onde onChangedispara após desfoque.

Ao realizar vários testes, não consigo dizer como esses dois eventos são diferentes (quando aplicados a uma textarea). Alguém pode lançar alguma luz sobre isso?

ffxsam
fonte
1
Eu editei minha postagem para ficar mais claro. Eu estava falando especificamente sobre textarea, não botões de rádio ou caixas de seleção.
ffxsam
Isso é muito falso, React não é apenas JS. E os eventos se comportam de maneira um pouco diferente em alguns casos (como onChange). E não, colar texto em uma textarea (no React) aciona onChangee onInput. Sinta-se à vontade para testar um violino e você verá.
ffxsam
Para <input> e <textarea>, onChange substitui - e geralmente deve ser usado em vez de - o manipulador de eventos oninput integrado do DOM.
Roko C. Buljan
Suponho que onChange seja a aposta mais segura. Eu até tentei alterar programaticamente o valor da textarea, pensando que talvez onChangefosse disparar e onInputnão iria, mas ambos disparariam.
ffxsam
Sim, agora, depois de revisar um pouco do React Docs, vejo que o React faz algumas coisas como jQuery, normaliza eventos e sim. onChange parece ser a forma preferida. E sim. React nada mais é do que JS. Não há mágica especial. Apenas regras.
Roko C. Buljan

Respostas:

79

Parece que não há diferença real

O React, por algum motivo, anexa ouvintes de Component.onChangeao element.oninputevento DOM . Veja a nota nos documentos sobre formulários:

React docs - Formulários

Há mais pessoas que se surpreendem com esse comportamento. Para obter mais detalhes, consulte este problema no rastreador de problemas React:

Documente como o onChange do React se relaciona com o onInput # 3964

Cite os comentários sobre esse assunto:

Não entendo por que o React escolheu fazer o onChange se comportar como o onInput. Pelo que posso dizer, não temos como recuperar o antigo comportamento onChange. Os documentos afirmam que é um "nome impróprio", mas não é realmente; ele dispara quando há uma mudança, mas não até que a entrada também perca o foco.

Para validação, às vezes não queremos mostrar erros de validação até que eles terminem de digitar. Ou talvez simplesmente não queiramos renderizar novamente a cada pressionamento de tecla. Agora, a única maneira de fazer isso é com onBlur, mas agora também precisamos verificar se o valor foi alterado manualmente.

Não é grande coisa, mas me parece que o React descartou um evento útil e se desviou do comportamento padrão quando já havia um evento que faz isso.

Concordo 100% com o comentário ... Mas acho que mudá-lo agora traria mais problemas do que resolve, uma vez que já havia muito código escrito que depende desse comportamento.

React não faz parte da coleção oficial de APIs da Web

Embora o React seja construído em cima do JS e tenha visto uma grande taxa de adoção, como uma tecnologia, o React existe para ocultar uma grande quantidade de funcionalidades sob sua própria API (relativamente pequena). Uma vez que a área onde isso é óbvio está no sistema de eventos, onde há muita coisa acontecendo sob a superfície que é radicalmente diferente do sistema de eventos DOM padrão. Não apenas em termos de quais eventos fazem o quê, mas também em termos de quando os dados podem persistir em qual estágio do tratamento de eventos. Você pode ler mais sobre isso aqui:

React Event System

Stijn de Witt
fonte
O parágrafo final é enganoso / falso.
rounce
1
React não é uma estrutura (onde fornece roteamento, persistência, gerenciamento de E / S de rede, etc.?), É uma biblioteca que fornece a abstração central para manipular árvores de exibição por meio de back-ends específicos de plataforma (react-dom, react-native, etc.).
rounce
7
Uau OK. Eu meio que concordo que é mais uma biblioteca do que uma estrutura, mas chamar o parágrafo de enganoso / falso por causa disso ?? Também discordo da noção de que um framework deve fornecer todos os aspectos de uma aplicação web ... Existem frameworks de roteamento, por exemplo, ou coisas como redux, que é um framework de gerenciamento de estado. Em minha mente, uma estrutura permite preencher as peças de uma máquina em funcionamento. No caso do Redux, você preenche redutores. No caso do Express, você preenche os gerenciadores de solicitações e middleware. Etc. Mas a distinção é uma área cinzenta para dizer o mínimo.
Stijn de Witt
4
Concordo plenamente. discutir sobre a distinção entre biblioteca e estrutura é realmente uma perda de tempo. depende apenas do nível de abstração em que você está trabalhando.
swyx de
1
@chadsteele Obrigado amigo, muito bom saber que ajudou você
Stijn de Witt
21

Não há diferença

React não tem o comportamento de evento padrão 'onChange'. O 'onChange' que vemos em react tem o comportamento do evento padrão 'onInput'. Portanto, para responder à sua pergunta, não há diferença na reação de ambos. Eu levantei um problema no GitHub em relação ao mesmo e isto é o que eles têm a dizer sobre isso:

Acho que na época em que essa decisão foi tomada (~ 4 anos atrás?), OnInput não funcionava de forma consistente entre os navegadores e confundia as pessoas que vinham de outras plataformas para a web, já que esperavam o evento de "mudança" para fogo em cada mudança. No caso do React, é um problema maior porque se você não conseguir lidar com a mudança em breve, as entradas controladas nunca serão atualizadas, levando as pessoas a pensarem que o React está quebrado. Então, a equipe decidiu chamá-lo para a mudança.

Em retrospecto, pode ter sido uma ideia melhor polyfill onInput e manter seu nome, em vez de alterar o comportamento de outro evento. Mas aquele navio navegou há muito tempo. Podemos revisar essa decisão no futuro, mas eu apenas encorajaria você a tratá-la como uma peculiaridade do React DOM (com a qual você se acostumará rapidamente).

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

Além disso, este artigo fornecerá mais informações. Como solução alternativa para a falta de 'onChange' padrão, o artigo sugere ouvir o evento 'onBlur'.

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

Nikhil Goyal
fonte
3

Recentemente, recebi um bug que onChangenão permitia copiar e colar no campo de entrada do IE11. Considerando que o onInputevento permitiria esse comportamento. Não consegui encontrar nenhuma documentação que descrevesse isso nos documentos, mas mostra que há uma diferença entre os dois (esperada ou não).

Alan souza
fonte
2

Como você pode ver em vários comentários aqui, o React trata onChange e onInput da mesma forma, em vez de debater o mérito dessa decisão. Aqui está a solução.

Use onBlur quando não quiser processar as edições do usuário até que estejam concluídas. :)

Chad Steele
fonte
1

Para qualquer um que tenha tropeçado nesse problema procurando uma maneira de ouvir o changeevento real baseado em DOM , foi assim que eu fiz (escrito em 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} />;
    }
}

Informe-nos se encontrar maneiras de melhorar essa abordagem ou se encontrar problemas com ela. Ao contrário blur, o changeevento também é disparado quando o usuário pressiona enter e só é disparado se o valor realmente mudou.

Ainda estou ganhando experiência com este CustomInputcomponente. Por exemplo, as caixas de seleção se comportam de maneira estranha. Eu tenho que inverter event.target.checkedno onChangemanipulador ao passar o valor para a caixa de seleção com checkedou me livrar dessa inversão ao passar o valor para a caixa de seleção com, defaultCheckedmas isso interrompe que várias caixas de seleção representando o mesmo estado em diferentes lugares na página se mantêm em sincronia . (Em ambos os casos, não passei um onInputmanipulador para as CustomInputcaixas de seleção.)

Kaspar Etter
fonte