<input>
O componente <input>
do navegador integrado permite que você renderize diferentes tipos de entradas de formulário.
<input />
Referência
<input>
Para exibir uma entrada, renderize o componente <input>
do navegador integrado.
<input name="myInput" />
Props
O componente <input>
aceita todas as props comuns de elementos.
formAction
: Uma string ou função. Substitui o<form action>
pai paratype="submit"
etype="image"
. Quando uma URL for passada paraaction
, o formulário se comportará como um formulário HTML padrão. Quando uma função é passada paraformAction
, a função manipulará o envio do formulário. Veja<form action>
.
Você pode tornar uma entrada controlada passando uma dessas props:
checked
: Um booleano. Para uma entrada do tipo checkbox ou um botão de rádio, controla se está selecionado.value
: Uma string. Para uma entrada de texto, controla o seu texto. (Para um botão de rádio, especifica seus dados de formulário.)
Quando você passa qualquer uma delas, também deve passar um manipulador onChange
que atualiza o valor passado.
Essas props do componente <input>
são relevantes apenas para entradas não controladas:
defaultChecked
: Um booleano. Especifica o valor inicial para entradas do tipotype="checkbox"
etype="radio"
.defaultValue
: Uma string. Especifica o valor inicial para uma entrada de texto.
Essas props do componente <input>
são relevantes tanto para entradas não controladas quanto para controladas:
accept
: Uma string. Especifica quais tipos de arquivo 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 preenchimento automático.autoFocus
: Um booleano. Setrue
, o React 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á esmaecida.children
: O componente<input>
não aceitachildren
.form
: Uma string. Especifica oid
do componente<form>
a que esta entrada pertence. Se omitido, é o formulário pai mais próximo.formAction
: Uma string. Substitui o<form action>
pai paratype="submit"
etype="image"
.formEnctype
: Uma string. Substitui o<form enctype>
pai paratype="submit"
etype="image"
.formMethod
: Uma string. Substitui o<form method>
pai paratype="submit"
etype="image"
.formNoValidate
: Uma string. Substitui o<form noValidate>
pai paratype="submit"
etype="image"
.formTarget
: Uma string. Substitui o<form target>
pai paratype="submit"
etype="image"
.height
: Uma string. Especifica a altura da imagem paratype="image"
.list
: Uma string. Especifica oid
do componente<datalist>
com as opções de preenchimento automático.max
: Um número. Especifica o valor máximo das 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 das 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 vários valores são permitidos para<type="file"
etype="email"
.name
: Uma string. Especifica o nome para esta entrada que é enviada com o formulário.onChange
: Uma função deEvent
handler. Requerido para entradas controladas. Dispara imediatamente quando o valor da entrada é alterado pelo usuário (por exemplo, dispara a cada pressionamento de tecla). Comporta-se como o eventoinput
do navegador.onChangeCapture
: Uma versão doonChange
que dispara na fase de captura.onInput
: Uma função deEvent
handler. Dispara imediatamente quando o valor é alterado pelo usuário. Por razões históricas, no React é idiomático usaronChange
em vez disso, que funciona de forma semelhante.onInputCapture
: Uma versão doonInput
que dispara na fase de captura.onInvalid
: Uma função deEvent
handler. Dispara se uma entrada falhar na validação ao enviar o formulário. Diferente do eventoinvalid
integrado, o eventoonInvalid
do React propaga.onInvalidCapture
: Uma versão doonInvalid
que dispara na fase de captura.onSelect
: Uma função deEvent
handler. Dispara após a alteração da seleção dentro do componente<input>
. 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 doonSelect
que dispara na fase de captura.pattern
: Uma string. Especifica o padrão que ovalue
deve corresponder.placeholder
: Uma string. Exibido em uma cor esmaecida quando o valor da entrada está vazio.readOnly
: Um booleano. Setrue
, a entrada não é editável pelo usuário.required
: Um booleano. Setrue
, o valor deve ser fornecido para o formulário ser 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 precisam de
checked
(oudefaultChecked
), não devalue
(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
booleana, ele será tratado como controlado. - Uma entrada não pode ser controlada e não controlada ao mesmo tempo.
- Uma entrada não pode alternar entre ser controlada ou não controlada durante sua vida útil.
- Toda entrada controlada precisa de um manipulador de evento
onChange
que atualiza o valor de apoio de forma síncrona.
Uso
Exibindo entradas 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 uma 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 uma entrada
Normalmente, você colocará cada <input>
dentro de uma tag <label>
. Isso informa ao navegador que este rótulo está associado a essa entrada. Quando o usuário clica no rótulo, o navegador focará automaticamente na entrada. 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>
em um componente <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 esse 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 uma entrada
Você pode opcionalmente especificar o valor inicial para qualquer entrada. Passe-o como string defaultValue
para entradas de texto. Checkboxes e botões de rádio devem especificar o valor inicial com o booleano defaultChecked
em vez disso.
export default function MyForm() { return ( <> <label> Entrada de texto: <input name="myInput" defaultValue="Some initial value" /> </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. Ele chamará seu manipulador de 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) { // Impede que o navegador recarregue a página e.preventDefault(); // Leia os dados do formulário const form = e.target; const formData = new FormData(form); // Você pode passar formData como um body de busca 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="Some initial value" /> </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">Reset form</button> <button type="submit">Enviar formulário</button> </form> ); }
Controlando uma entrada com uma variável de estado
Uma entrada como <input />
não é controlada. Mesmo se você passar um valor inicial como <input defaultValue="Texto inicial" />
, seu JSX apenas especifica o valor inicial. Ele não controla qual deve ser o valor agora.
Para renderizar uma entrada controlada, passe a prop value
para ela (ou checked
para checkboxes e rádios). O React forçará a entrada 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 da entrada a corresponder à variável de estado...
onChange={e => setFirstName(e.target.value)} // ... e atualizar a variável de estado em qualquer edição!
/>
);
}
Uma entrada controlada faz sentido se você precisasse de estado de qualquer maneira - por exemplo, para renderizar sua UI a 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ê deseja oferecer várias maneiras de ajustar o estado da entrada (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 esteja vazio (como no campo firstName
abaixo), inicialize sua variável de estado com 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 renderização a cada pressionamento de tecla
Quando você usa uma entrada controlada, você define o estado a cada pressionamento de tecla. Se o componente que contém seu estado renderizar uma árvore grande, isso pode ficar lento. Existem algumas maneiras de otimizar o desempenho da renderização.
Por exemplo, suponha que você comece com um formulário que renderiza todo o conteúdo da página a cada pressionamento de tecla:
function App() {
const [firstName, setFirstName] = useState('');
return (
<>
<form>
<input value={firstName} onChange={e => setFirstName(e.target.value)} />
</form>
<PageContent />
</>
);
}
Como o <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 somente SignupForm
renderiza a cada pressionamento de tecla.
Se não houver como evitar a renderização (por exemplo, se PageContent
depender do valor da entrada de pesquisa), useDeferredValue
permite que você mantenha a entrada controlada responsiva mesmo no meio de uma grande renderização.
Solução de problemas
Minha entrada de texto não atualiza quando digito nela
Se você renderizar uma entrada com value
, mas sem onChange
, verá um erro no console:
// 🔴 Bug: entrada de texto controlada sem manipulador onChange
<input value={something} />
value
para um campo de formulário sem um manipulador onChange
. Isso renderizará um campo somente leitura. Se o campo deve ser mutável, use defaultValue
. Caso contrário, defina onChange
ou readOnly
.Como a mensagem de erro sugere, se você só queria especificar o valor inicial, passe defaultValue
em vez disso:
// ✅ Bom: entrada não controlada com um valor inicial
<input defaultValue={something} />
Se você quer controlar esta entrada 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 alteração
<input value={something} readOnly={true} />
Minha checkbox não atualiza quando clico nela
Se você renderizar uma checkbox com checked
, mas sem onChange
, verá um erro no console:
// 🔴 Bug: checkbox controlada sem manipulador onChange
<input type="checkbox" checked={something} />
checked
para um campo de formulário sem um manipulador onChange
. Isso renderizará um campo somente leitura. Se o campo deve ser mutável, use defaultChecked
. Caso contrário, defina onChange
ou readOnly
.Como a mensagem de erro sugere, se você só queria especificar o valor inicial, passe defaultChecked
em vez disso:
// ✅ Bom: checkbox não controlada com um valor inicial
<input type="checkbox" defaultChecked={something} />
Se você quer controlar esta checkbox com uma variável de estado, especifique um manipulador onChange
:
// ✅ Bom: checkbox controlada com onChange
<input type="checkbox" checked={something} onChange={e => setSomething(e.target.checked)} />
Se a checkbox for intencionalmente somente leitura, adicione uma prop readOnly
para suprimir o erro:
// ✅ Bom: entrada controlada somente leitura sem alteração
<input type="checkbox" checked={something} readOnly={true} />
Meu cursor de entrada pula para o início a cada pressionamento de tecla
Se você controla uma entrada, você deve atualizar sua variável de estado para o valor da entrada 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 uma entrada 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 uma entrada de forma assíncrona
setTimeout(() => {
setFirstName(e.target.value);
}, 100);
}
Para corrigir seu código, atualize-o de forma síncrona para e.target.value
:
function handleChange(e) {
// ✅ Atualizando uma entrada controlada para e.target.value de forma síncrona
setFirstName(e.target.value);
}
Se isso não resolver o problema, é possível que a entrada seja removida e readicionada do DOM a cada pressionamento de tecla. Isso pode acontecer se você estiver redefinindo acidentalmente o estado a cada renderização, por exemplo, se a entrada ou um de seus pais sempre receber um atributo key
diferente, ou se você aninhar definições de função de componente (o que não é suportado e faz com que o componente “interno” seja sempre considerado uma árvore diferente).
Estou recebendo um erro: “Um componente está alterando uma entrada não controlada para ser controlada”
Se você fornecer um value
para o componente, ele deve permanecer uma string durante sua vida útil.
Você não pode passar value={undefined}
primeiro e depois passar value="some string"
porque o React não saberá se você deseja que o componente seja não controlado ou controlado. Um componente controlado sempre deve 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, defina-o como uma string vazia (''
) inicialmente ou passe value={someValue ?? ''}
para garantir que value
seja uma string.
Da mesma forma, se você passar checked
para uma checkbox, certifique-se de que seja sempre um booleano.