O componente nativo do navegador <textarea> permite renderizar uma entrada de texto de várias linhas.

<textarea />

Referência

<textarea>

Para exibir uma área de texto, renderize o componente nativo do navegador <textarea>.

<textarea name="postContent" />

Veja mais exemplos abaixo.

Props

O <textarea> suporta todas as props comuns de elementos.

Você pode transformar uma área de texto em controlada passando uma prop value:

  • value: Uma string. Controla o texto dentro da área de texto.

Quando você passa value, você também deve passar um manipulador onChange que atualiza o valor passado.

Se o seu <textarea> não for controlado, você pode passar a prop defaultValue em vez disso:

  • defaultValue: Uma string. Especifica o valor inicial para uma área de texto.

Essas props do <textarea> são relevantes tanto para áreas de texto não controladas quanto para áreas de texto controladas:

  • autoComplete: Ou 'on' ou 'off'. Especifica o comportamento de preenchimento automático.
  • autoFocus: Um booleano. Se true, o React irá focar no elemento ao montar.
  • children: <textarea> não aceita filhos. Para definir o valor inicial, use defaultValue.
  • cols: Um número. Especifica a largura padrão em larguras médias de caracteres. O padrão é 20.
  • disabled: Um booleano. Se true, a entrada não será interativa e aparecerá esmaecida.
  • form: Uma string. Especifica o id do <form> ao qual esta entrada pertence. Se omitido, é o formulário pai mais próximo.
  • maxLength: Um número. Especifica o comprimento máximo do texto.
  • minLength: Um número. Especifica o comprimento mínimo do texto.
  • name: Uma string. Especifica o nome para esta entrada que é enviada com o formulário.
  • onChange: Uma função de Event handler. Necessário para áreas de texto controladas. Dispara imediatamente quando o valor da entrada é alterado pelo usuário (por exemplo, ele dispara a cada pressionamento de tecla). Comporta-se como o evento input do navegador.
  • onChangeCapture: Uma versão de onChange que dispara na fase de captura.
  • onInput: Uma função de Event handler. Dispara imediatamente quando o valor é alterado pelo usuário. Por razões históricas, no React é idiomático usar onChange em vez disso, que funciona de forma semelhante.
  • onInputCapture: Uma versão de onInput que dispara na fase de captura.
  • onInvalid: Uma função de Event handler. Dispara se uma entrada falha na validação no envio do formulário. Ao contrário do evento invalid nativo, o evento onInvalid do React propaga.
  • onInvalidCapture: Uma versão de onInvalid que dispara na fase de captura.
  • onSelect: Uma função de Event handler. Dispara após a alteração da seleção dentro do <textarea>. O React estende o evento onSelect para também disparar para seleção vazia e em edições (o que pode afetar a seleção).
  • onSelectCapture: Uma versão de onSelect que dispara na fase de captura.
  • placeholder: Uma string. Exibido em uma cor esmaecida quando o valor da área de texto está vazio.
  • readOnly: Um booleano. Se true, a área de texto não é editável pelo usuário.
  • required: Um booleano. Se true, o valor deve ser fornecido para que o formulário seja enviado.
  • rows: Um número. Especifica a altura padrão em alturas médias de caracteres. O padrão é 2.
  • wrap: Ou 'hard', 'soft', ou 'off'. Especifica como o texto deve ser quebrado ao enviar um formulário.

Caveats

  • Passar filhos como <textarea>something</textarea> não é permitido. Use defaultValue para conteúdo inicial.
  • Se uma área de texto receber uma prop string value, ela será tratada como controlada.
  • Uma área de texto não pode ser controlada e não controlada ao mesmo tempo.
  • Uma área de texto não pode alternar entre ser controlada ou não controlada durante sua vida útil.
  • Toda área de texto controlada precisa de um manipulador de eventos onChange que atualize de forma síncrona seu valor de backup.

Uso

Exibindo uma área de texto

Renderize <textarea> para exibir uma área de texto. Você pode especificar seu tamanho padrão com os atributos rows e cols, mas, por padrão, o usuário poderá redimensioná-la. Para desativar o redimensionamento, você pode especificar resize: none no CSS.

export default function NewPost() {
  return (
    <label>
      Escreva sua postagem:
      <textarea name="postContent" rows={4} cols={40} />
    </label>
  );
}


Fornecendo um rótulo para uma área de texto

Normalmente, você colocará cada <textarea> dentro de uma tag <label>. Isso informa ao navegador que este rótulo está associado àquela área de texto. Quando o usuário clica no rótulo, o navegador vai focar na área de texto. Também é essencial para acessibilidade: um leitor de tela anunciará a legenda do rótulo quando o usuário focar na área de texto.

Se você não puder aninhar <textarea> em um <label>, associe-os passando o mesmo ID para <textarea id> e <label htmlFor>. Para evitar conflitos entre instâncias de um componente, gere tal ID com useId.

import { useId } from 'react';

export default function Form() {
  const postTextAreaId = useId();
  return (
    <>
      <label htmlFor={postTextAreaId}>
        Escreva sua postagem:
      </label>
      <textarea
        id={postTextAreaId}
        name="postContent"
        rows={4}
        cols={40}
      />
    </>
  );
}


Fornecendo um valor inicial para uma área de texto

Você pode opcionalmente especificar o valor inicial para a área de texto. Passe-o como a string defaultValue.

export default function EditPost() {
  return (
    <label>
      Edite sua postagem:
      <textarea
        name="postContent"
        defaultValue="Eu realmente gostei de andar de bicicleta ontem!"
        rows={4}
        cols={40}
      />
    </label>
  );
}

Pitfall

Ao contrário do HTML, passar um texto inicial como <textarea>Algum conteúdo</textarea> não é suportado.


Lendo o valor da área de texto ao enviar um formulário

Adicione um <form> em torno de sua textarea com um <button type="submit"> dentro. Ele chamará seu manipulador de eventos <form onSubmit>. Por padrão, o navegador enviará os dados do formulário para o 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 EditPost() {
  function handleSubmit(e) {
    // Evite 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 corpo 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>
        Título da postagem: <input name="postTitle" defaultValue="Biking" />
      </label>
      <label>
        Edite sua postagem:
        <textarea
          name="postContent"
          defaultValue="Eu realmente gostei de andar de bicicleta ontem!"
          rows={4}
          cols={40}
        />
      </label>
      <hr />
      <button type="reset">Redefinir edições</button>
      <button type="submit">Salvar postagem</button>
    </form>
  );
}

Note

Dê um name para seu <textarea>, por exemplo <textarea name="postContent" />. O name que você especificou será usado como uma chave nos dados do formulário, por exemplo { postContent: "Sua postagem" }.

Pitfall

Por padrão, qualquer <button> dentro de um <form> o enviará. Isso pode ser surpreendente! Se você tiver seu próprio componente Button do React personalizado, considere retornar <button type="button"> em vez de <button>. Então, para ser explícito, use <button type="submit"> para os botões que devem enviar o formulário


Controlando uma área de texto com uma variável de estado

Uma área de texto como <textarea /> é não controlada. Mesmo se você passar um valor inicial como <textarea defaultValue="Text initial" />, seu JSX especifica apenas o valor inicial, não o valor agora.

Para renderizar uma área de texto controlada, passe a prop value para ela. React irá forçar a área de texto a sempre ter o value que você passou. Normalmente, você controlará uma área de texto declarando uma variável de estado:

function NewPost() {
const [postContent, setPostContent] = useState(''); // Declare uma variável de estado...
// ...
return (
<textarea
value={postContent} // ...force o valor da entrada para corresponder à variável de estado...
onChange={e => setPostContent(e.target.value)} // ... e atualize a variável de estado em qualquer edição!
/>
);
}

Isso é útil se você deseja re-renderizar alguma parte da UI em resposta a cada pressionamento de tecla.

{
  "dependencies": {
    "react": "latest",
    "react-dom": "latest",
    "react-scripts": "latest",
    "remarkable": "2.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "devDependencies": {}
}

Pitfall

Se você passar value sem onChange, será impossível digitar na área de texto. Quando você controla uma área de texto passando algum value para ela, você a força a sempre ter o valor que você passou. Então, se você passar uma variável de estado como um value, mas esquecer de atualizar essa variável de estado de forma síncrona durante o manipulador de eventos onChange, o React reverterá a área de texto após cada pressionamento de tecla para o value que você especificou


Solução de problemas

Minha área de texto não atualiza quando digito nela

Se você renderizar uma área de texto com value mas sem onChange, você verá um erro no console:

// 🔴 Bug: área de texto controlada sem manipulador onChange
<textarea value={something} />
Console
Você forneceu uma prop 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ó quisesse especificar o valor inicial, passe defaultValue em vez disso:

// ✅ Bom: área de texto não controlada com um valor inicial
<textarea defaultValue={something} />

Se você quiser controlar esta área de texto com uma variável de estado, especifique um manipulador de onChange:

// ✅ Bom: área de texto controlada com onChange
<textarea value={something} onChange={e => setSomething(e.target.value)} />

Se o valor for intencionalmente somente leitura, adicione uma prop readOnly para suprimir o erro:

// ✅ Bom: área de texto controlada somente leitura sem alteração
<textarea value={something} readOnly={true} />

Meu cursor da área de texto salta para o início a cada pressionamento de tecla

Se você controla uma área de texto, você deve atualizar sua variável de estado para o valor da área de texto do DOM durante onChange.

Você não pode atualizá-lo para algo diferente de e.target.value:

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 área de texto seja removida e readicionada do DOM a cada pressionamento de tecla. Isso pode acontecer se você estiver acidentalmente redefinindo o estado a cada re-renderização. Por exemplo, isso pode acontecer se a área de texto ou um de seus pais sempre receber um atributo key diferente, ou se você aninhar definições de componentes (o que não é permitido no React e faz com que o componente “interno” seja remontado a cada renderização).


Estou recebendo um erro: “Um componente está mudando uma entrada não controlada para ser controlada”

Se você fornecer um value para o componente, ele deverá 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 sempre deve receber um value string, não null ou undefined.

Se o seu value está vindo de um API ou uma variável de estado, ele pode ser inicializado para null ou undefined. Nesse caso, ou defina-o para uma string vazia ('') inicialmente, ou passe value={someValue ?? ''} para garantir que value seja uma string.