<input>
O componente de <input>
embarcado no navegador permite renderizar diferentes tipos de entradas de formulário.
<input />
Referência
<input>
Para exibir uma entrada, renderize o componente de <input>
embarcado no navegador.
<input name="myInput" />
Props
<input>
suporta todas as props de elemento comuns.
formAction
: Uma string ou função. Substitui a <form action>
do pai para type="submit"
e type="image"
. Quando uma URL é passada para action
, o formulário se comportará como um formulário HTML padrão. Quando uma função é passada para formAction
, a função lidará com a submissão do formulário. Veja <form action>
.
Você pode tornar um input controlado passando uma dessas props:
checked
: Um booleano. Para uma entrada de checkbox ou um botão de rádio, controla se ele está selecionado.value
: Uma string. Para uma entrada de texto, controla seu texto. (Para um botão de rádio, especifica seus dados de formulário.)
Ao passar qualquer um deles, você também deve passar um manipulador onChange
que atualiza o valor passado.
Essas props <input>
são relevantes apenas para entradas não controladas:
defaultChecked
: Um booleano. Especifica o valor inicial para entradastype="checkbox"
etype="radio"
.defaultValue
: Uma string. Especifica o valor inicial para uma entrada de texto.
Essas props <input>
são relevantes tanto para entradas não controladas quanto controladas:
accept
: Uma string. Especifica quais tipos de arquivos são aceitos por uma entradatype="file"
.alt
: Uma string. Especifica o texto alternativo da imagem para uma entradatype="image"
.capture
: Uma string. Especifica a mídia (microfone, vídeo ou câmera) capturada por uma entradatype="file"
.autoComplete
: Uma string. Especifica um dos possíveis comportamentos de autocomplete.autoFocus
: Um booleano. Setrue
, o React irá focar o elemento na montagem.dirname
: Uma string. Especifica o nome do campo do formulário para a direcionalidade do elemento.disabled
: Um booleano. Setrue
, a entrada não será interativa e aparecerá desbotada.children
:<input>
não aceita filhos.form
: Uma string. Especifica oid
da<form>
à qual esta entrada pertence. Se omitido, é o formulário pai mais próximo.formAction
: Uma string. Substitui a<form action>
do pai paratype="submit"
etype="image"
.formEnctype
: Uma string. Substitui a<form enctype>
do pai paratype="submit"
etype="image"
.formMethod
: Uma string. Substitui a<form method>
do pai paratype="submit"
etype="image"
.formNoValidate
: Uma string. Substitui a<form noValidate>
do pai paratype="submit"
etype="image"
.formTarget
: Uma string. Substitui a<form target>
do pai paratype="submit"
etype="image"
.height
: Uma string. Especifica a altura da imagem paratype="image"
.list
: Uma string. Especifica oid
do<datalist>
com as opções de autocomplete.max
: Um número. Especifica o valor máximo de entradas numéricas e de data/hora.maxLength
: Um número. Especifica o comprimento máximo de texto e outras entradas.min
: Um número. Especifica o valor mínimo de entradas numéricas e de data/hora.minLength
: Um número. Especifica o comprimento mínimo de texto e outras entradas.multiple
: Um booleano. Especifica se múltiplos valores são permitidos para<type="file"
etype="email"
.name
: Uma string. Especifica o nome desta entrada que será submetido com o formulário.onChange
: Uma funçãoEvent
handler. Necessária para entradas controladas. Dispara imediatamente quando o valor do input é alterado pelo usuário (por exemplo, dispara a cada tecla pressionada). Comporta-se como o eventoinput
do navegador.onChangeCapture
: Uma versão deonChange
que dispara na fase de captura.onInput
: Uma funçãoEvent
handler. Dispara imediatamente quando o valor é alterado pelo usuário. Por razões históricas, no React é idiomático usaronChange
, que funciona de forma semelhante.onInputCapture
: Uma versão deonInput
que dispara na fase de captura.onInvalid
: Uma funçãoEvent
handler. Dispara se uma entrada falhar na validação ao enviar o formulário. Ao contrário do eventoinvalid
embutido, o evento ReactonInvalid
propaga.onInvalidCapture
: Uma versão deonInvalid
que dispara na fase de captura.onSelect
: Uma funçãoEvent
handler. Dispara após a seleção dentro do<input>
mudar. O React estende o eventoonSelect
para também disparar para seleção vazia e em edições (que podem afetar a seleção).onSelectCapture
: Uma versão deonSelect
que dispara na fase de captura.pattern
: Uma string. Especifica o padrão que ovalue
deve corresponder.placeholder
: Uma string. Exibida em uma cor desbotada quando o valor do input está vazio.readOnly
: Um booleano. Setrue
, a entrada não pode ser editada pelo usuário.required
: Um booleano. Setrue
, o valor deve ser fornecido para que o formulário seja enviado.size
: Um número. Semelhante a definir a largura, mas a unidade depende do controle.src
: Uma string. Especifica a fonte da imagem para uma entradatype="image"
.step
: Um número positivo ou uma string'any'
. Especifica a distância entre valores válidos.type
: Uma string. Um dos tipos de entrada.width
: Uma string. Especifica a largura da imagem para uma entradatype="image"
.
Ressalvas
- Checkboxes necessitam de
checked
(oudefaultChecked
), nãovalue
(oudefaultValue
). - Se uma entrada de texto receber uma prop
value
string, ela será tratada como controlada. - Se um checkbox ou um botão de rádio receber uma prop
checked
booleano, ele será tratado como controlado. - Um input não pode ser controlado e não controlado ao mesmo tempo.
- Um input não pode alternar entre ser controlado ou não controlado ao longo de sua vida útil.
- Cada input controlado precisa de um manipulador de eventos
onChange
que atualiza sincronicamente seu valor de suporte.
Uso
Exibindo inputs de diferentes tipos
Para exibir uma entrada, renderize um componente <input>
. Por padrão, será uma entrada de texto. Você pode passar type="checkbox"
para um checkbox, type="radio"
para um botão de rádio, ou um dos outros tipos de entrada.
export default function MyForm() { return ( <> <label> Entrada de texto: <input name="myInput" /> </label> <hr /> <label> Checkbox: <input type="checkbox" name="myCheckbox" /> </label> <hr /> <p> Botões de rádio: <label> <input type="radio" name="myRadio" value="option1" /> Opção 1 </label> <label> <input type="radio" name="myRadio" value="option2" /> Opção 2 </label> <label> <input type="radio" name="myRadio" value="option3" /> Opção 3 </label> </p> </> ); }
Fornecendo um rótulo para um input
Normalmente, você colocará cada <input>
dentro de uma tag <label>
. Isso informa ao navegador que esse rótulo está associado a essa entrada. Quando o usuário clica no rótulo, o navegador automaticamente focará a entrada. Isso também é essencial para acessibilidade: um leitor de tela anunciará a legenda do rótulo quando o usuário focar na entrada associada.
Se você não puder aninhar <input>
dentro de um <label>
, associe-os passando o mesmo ID para <input id>
e <label htmlFor>
. Para evitar conflitos entre várias instâncias de um componente, gere tal ID com useId
.
import { useId } from 'react'; export default function Form() { const ageInputId = useId(); return ( <> <label> Seu primeiro nome: <input name="firstName" /> </label> <hr /> <label htmlFor={ageInputId}>Sua idade:</label> <input id={ageInputId} name="age" type="number" /> </> ); }
Fornecendo um valor inicial para um input
Você pode opcionalmente especificar o valor inicial para qualquer entrada. Passe-o como a string defaultValue
para entradas de texto. Checkboxes e botões de rádio devem especificar o valor inicial com a prop defaultChecked
booleano.
export default function MyForm() { return ( <> <label> Entrada de texto: <input name="myInput" defaultValue="Algum valor inicial" /> </label> <hr /> <label> Checkbox: <input type="checkbox" name="myCheckbox" defaultChecked={true} /> </label> <hr /> <p> Botões de rádio: <label> <input type="radio" name="myRadio" value="option1" /> Opção 1 </label> <label> <input type="radio" name="myRadio" value="option2" defaultChecked={true} /> Opção 2 </label> <label> <input type="radio" name="myRadio" value="option3" /> Opção 3 </label> </p> </> ); }
Lendo os valores de entrada ao enviar um formulário
Adicione um <form>
ao redor de suas entradas com um <button type="submit">
dentro. Isso chamará seu evento <form onSubmit>
. Por padrão, o navegador enviará os dados do formulário para a URL atual e atualizará a página. Você pode substituir esse comportamento chamando e.preventDefault()
. Leia os dados do formulário com new FormData(e.target)
.
export default function MyForm() { function handleSubmit(e) { // Impedir que o navegador recarregue a página e.preventDefault(); // Ler os dados do formulário const form = e.target; const formData = new FormData(form); // Você pode passar formData como um corpo de fetch diretamente: fetch('/some-api', { method: form.method, body: formData }); // Ou você pode trabalhar com ele como um objeto simples: const formJson = Object.fromEntries(formData.entries()); console.log(formJson); } return ( <form method="post" onSubmit={handleSubmit}> <label> Entrada de texto: <input name="myInput" defaultValue="Algum valor inicial" /> </label> <hr /> <label> Checkbox: <input type="checkbox" name="myCheckbox" defaultChecked={true} /> </label> <hr /> <p> Botões de rádio: <label><input type="radio" name="myRadio" value="option1" /> Opção 1</label> <label><input type="radio" name="myRadio" value="option2" defaultChecked={true} /> Opção 2</label> <label><input type="radio" name="myRadio" value="option3" /> Opção 3</label> </p> <hr /> <button type="reset">Redefinir formulário</button> <button type="submit">Enviar formulário</button> </form> ); }
Controlando um input com uma variável de estado
Um input como <input />
é não controlado. Mesmo que você passe um valor inicial como <input defaultValue="Texto inicial" />
, seu JSX apenas especifica o valor inicial. Não controla qual deve ser o valor agora.
Para renderizar um input controlado, passe a prop value
para ele (ou checked
para checkboxes e rádios). O React forçará o input a sempre ter o value
que você passou. Normalmente, você faria isso declarando uma variável de estado:
function Form() {
const [firstName, setFirstName] = useState(''); // Declare uma variável de estado...
// ...
return (
<input
value={firstName} // ...forçar o valor do input a corresponder à variável de estado...
onChange={e => setFirstName(e.target.value)} // ... e atualizar a variável de estado em qualquer edição!
/>
);
}
Um input controlado faz sentido se você precisasse de estado de qualquer maneira—por exemplo, para re-renderizar sua UI em cada edição:
function Form() {
const [firstName, setFirstName] = useState('');
return (
<>
<label>
Primeiro nome:
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</label>
{firstName !== '' && <p>Seu nome é {firstName}.</p>}
...
É também útil se você quiser oferecer várias maneiras de ajustar o estado do input (por exemplo, clicando em um botão):
function Form() {
// ...
const [age, setAge] = useState('');
const ageAsNumber = Number(age);
return (
<>
<label>
Idade:
<input
value={age}
onChange={e => setAge(e.target.value)}
type="number"
/>
<button onClick={() => setAge(ageAsNumber + 10)}>
Adicionar 10 anos
</button>
O value
que você passa para componentes controlados não deve ser undefined
ou null
. Se você precisar que o valor inicial seja vazio (como no campo firstName
abaixo), inicialize sua variável de estado como uma string vazia (''
).
import { useState } from 'react'; export default function Form() { const [firstName, setFirstName] = useState(''); const [age, setAge] = useState('20'); const ageAsNumber = Number(age); return ( <> <label> Primeiro nome: <input value={firstName} onChange={e => setFirstName(e.target.value)} /> </label> <label> Idade: <input value={age} onChange={e => setAge(e.target.value)} type="number" /> <button onClick={() => setAge(ageAsNumber + 10)}> Adicionar 10 anos </button> </label> {firstName !== '' && <p>Seu nome é {firstName}.</p> } {ageAsNumber > 0 && <p>Sua idade é {ageAsNumber}.</p> } </> ); }
Otimizando a re-renderização em cada tecla pressionada
Quando você usa um input controlado, você define o estado em cada tecla pressionada. Se o componente que contém seu estado re-renderiza uma árvore grande, isso pode ficar lento. Existem algumas maneiras de otimizar o desempenho da re-renderização.
Por exemplo, suponha que você comece com um formulário que re-renderiza todo o conteúdo da página a cada tecla pressionada:
function App() {
const [firstName, setFirstName] = useState('');
return (
<>
<form>
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</form>
<PageContent />
</>
);
}
Como <PageContent />
não depende do estado da entrada, você pode mover o estado da entrada para seu próprio componente:
function App() {
return (
<>
<SignupForm />
<PageContent />
</>
);
}
function SignupForm() {
const [firstName, setFirstName] = useState('');
return (
<form>
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</form>
);
}
Isso melhora significativamente o desempenho porque agora apenas o SignupForm
re-renderiza a cada tecla pressionada.
Se não houver como evitar a re-renderização (por exemplo, se PageContent
depender do valor da entrada de pesquisa), useDeferredValue
permite que você mantenha o input controlado responsivo mesmo no meio de uma grande re-renderização.
Solução de Problemas
Minha entrada de texto não atualiza quando digito nela
Se você renderizar um input com value
mas sem onChange
, verá um erro no console:
// 🔴 Bug: entrada de texto controlada sem manipulador onChange
<input value={something} />
value
a um campo de formulário sem um manipulador onChange
. Isso renderizará um campo somente leitura. Se o campo deveria ser mutável, use defaultValue
. Caso contrário, defina onChange
ou readOnly
.Como a mensagem de erro sugere, se você apenas quisesse especificar o *valor inicial, passe defaultValue
em vez disso:
// ✅ Bom: entrada não controlada com um valor inicial
<input defaultValue={something} />
Se você quiser controlar esse input com uma variável de estado, especifique um manipulador onChange
:
// ✅ Bom: entrada controlada com onChange
<input value={something} onChange={e => setSomething(e.target.value)} />
Se o valor for intencionalmente somente leitura, adicione uma prop readOnly
para suprimir o erro:
// ✅ Bom: entrada controlada somente leitura sem on change
<input value={something} readOnly={true} />
Meu checkbox não atualiza quando clico nele
Se você renderizar um checkbox com checked
mas sem onChange
, verá um erro no console:
// 🔴 Bug: checkbox controlado sem manipulador onChange
<input type="checkbox" checked={something} />
checked
a um campo de formulário sem um manipulador onChange
. Isso renderizará um campo somente leitura. Se o campo deveria ser mutável, use defaultChecked
. Caso contrário, defina onChange
ou readOnly
.Como a mensagem de erro sugere, se você apenas quisesse especificar o *valor inicial, passe defaultChecked
em vez disso:
// ✅ Bom: checkbox não controlado com um valor inicial
<input type="checkbox" defaultChecked={something} />
Se você quiser controlar esse checkbox com uma variável de estado, especifique um manipulador onChange
:
// ✅ Bom: checkbox controlado com onChange
<input type="checkbox" checked={something} onChange={e => setSomething(e.target.checked)} />
Se o checkbox for intencionalmente somente leitura, adicione uma prop readOnly
para suprimir o erro:
// ✅ Bom: entrada controlada somente leitura sem on change
<input type="checkbox" checked={something} readOnly={true} />
Meu cursor de entrada salta para o início a cada tecla pressionada
Se você controla um input, deve atualizar sua variável de estado para o valor do input do DOM durante onChange
.
Você não pode atualizá-lo para algo diferente de e.target.value
(ou e.target.checked
para checkboxes):
function handleChange(e) {
// 🔴 Bug: atualizando um input para algo diferente de e.target.value
setFirstName(e.target.value.toUpperCase());
}
Você também não pode atualizá-lo de forma assíncrona:
function handleChange(e) {
// 🔴 Bug: atualizando um input de forma assíncrona
setTimeout(() => {
setFirstName(e.target.value);
}, 100);
}
Para corrigir seu código, atualize-o sincronicamente para e.target.value
:
function handleChange(e) {
// ✅ Atualizando um input controlado para e.target.value sincronicamente
setFirstName(e.target.value);
}
Se isso não resolver o problema, é possível que o input esteja sendo removido e re-adicionado do DOM a cada tecla pressionada. Isso pode acontecer se você acidentalmente resetar o estado a cada re-renderização, por exemplo, se o input ou um de seus pais sempre recebe um atributo key
diferente, ou se você aninhar definições de funções de componentes (o que não é suportado e faz com que o “componente interno” sempre seja considerado uma árvore diferente).
Estou recebendo um erro: “Um componente está mudando um input não controlado para ser controlado”
Se você fornecer um value
ao componente, ele deve permanecer uma string durante toda a sua vida útil.
Você não pode passar value={undefined}
primeiro e depois passar value="alguma string"
porque o React não saberá se você deseja que o componente seja não controlado ou controlado. Um componente controlado deve sempre receber um value
string, não null
ou undefined
.
Se seu value
estiver vindo de uma API ou de uma variável de estado, ele pode ser inicializado como null
ou undefined
. Nesse caso, ou o defina como uma string vazia (''
) inicialmente, ou passe value={someValue ?? ''}
para garantir que value
seja uma string.
Da mesma forma, se você passar checked
para um checkbox, certifique-se de que ele seja sempre um booleano.