Você já se perguntou como construir um componente de campo de entrada de tag para seu aplicativo React? Veja como.
Primeiro, vamos começar com uma representação visual da marcação que vamos implementar. Precisamos de um contêiner envolvendo as tags e um campo de entrada. À medida que adicionamos mais tags, o campo de entrada é forçado ainda mais para a direita, o que dá a sensação de adicionar as tags ao campo de entrada.
Uma pseudo marcação correspondente à visualização acima seria algo como o seguinte.
{tags.map ((tag)=>{tag})}
Neste ponto, está claro que precisamos de uma variável de estado para armazenar as tags inseridas, bem como outra variável de estado para controlar o campo de entrada. Os estados input
e tags
serão string vazia e array vazio por padrão, respectivamente.
const [input, setInput]=useState (''); const [tags, setTags]=useState ([]);
A próxima coisa que precisamos é ouvir as mudanças no campo de entrada para que possamos definir o estado input
e criar uma lógica para preencher o estado tags
quando um determinada tecla é pressionada. Vamos supor que queremos separar as tags com vírgulas, então, quando essa tecla for pressionada, enviaremos o conteúdo do estado input
como um novo valor para o array tags
.
Para fazer isso, precisamos usar os eventos onChange
e onKeyDown
. Portanto, agora nossa marcação muda um pouco com os novos atributos adicionados:
{tags.map ((tag)=>{tag})}
Tipos de eventos de entrada
onChange
Este evento é necessário apenas para ouvir as alterações no campo de entrada e atualizar a variável de estado input
.
const onChange=(e)=> { const {valor}=e.target; setInput (valor);
};
onKeyDown
Ao contrário do evento onChange , o evento onKeyDown expõe a propriedade key
, que nos informa qual tecla do teclado é pressionada. Como queremos separar as tags com uma vírgula, em uma instrução if, precisamos verificar se key
é igual a ,
.
A segunda verificação que temos na instrução if é para garantir que a variável de estado input
não esteja vazia após o espaço em branco de ambos os lados da string ser removido por trim () método.
A última verificação de que precisamos é ter certeza de que a tag ainda não existe. Como armazenamos tags na variável de estado tags
, simplesmente verificamos se esse array contém o mesmo trimmedInput
. Caso contrário, podemos colocar essa nova tag na matriz tags
.
Assim que estivermos na instrução if, precisamos evitar o comportamento padrão chamando e.preventDefault ()
para que o caractere de vírgula não apareça no campo de entrada, mesmo que esteja registrado. Em seguida, coloque a tag na matriz tags
usando a função setTags
. Por fim, limpamos o campo de entrada passando uma string vazia para a função setInput
.
const onKeyDown=(e)=> { const {chave}=e; const trimmedInput=input.trim (); if (key===','&& trimmedInput.length &&! tags.includes (trimmedInput)) { e.preventDefault (); setTags (prevState=> [... prevState, trimmedInput]); setInput (''); } };
Agora, se você inserir um texto e pressionar a tecla de vírgula, verá a tag renderizada na parte superior do campo de entrada e que o campo de entrada será limpo.
Também precisamos ser capazes de excluir as tags quando a tecla backspace é pressionada, para o qual existem duas abordagens diferentes: Exclua a tag completamente de uma vez ou exclua a tag e retorne o conteúdo da tag ao campo de entrada para que o usuário pode editar a tag e enviar novamente. Vou mostrar a implementação da segunda abordagem.
Como precisamos ouvir o pressionamento de uma tecla backspace, usaremos o evento onKeyDown novamente.
Desta vez, key
deve ser igual a "Backspace"
. Também precisamos verificar se o campo de entrada está vazio e se o array tags
não está vazio.
Assim que essas condições forem mantidas, precisamos remover o último item da matriz tags
e colocar esse último elemento no campo de entrada.
Para fazer isso, estou simplesmente clonando a variável de estado tags
, espalhando-a em um novo array e, em seguida, atribuindo-a a uma nova variável chamada tagsCopy
. O motivo de criar um clone da matriz não é para alterar a variável de estado.
A seguir, chamo o método pop ()
nessa variável para obter o último elemento do array e também removê-lo do array. Este valor exibido agora é armazenado em uma variável chamada poppedTag
.
Usamos setTags
para atualizar o estado tags
com o array tagsCopy
, que é o array sem a última tag. E agora, precisamos daquele valor de tag exibido no campo de entrada, é por isso que chamamos setInput (poppedTag)
para atualizar a variável de estado input
com o último valor de tag.
const onKeyDown=(e)=> { const {chave}=e; const trimmedInput=input.trim (); if (key===','&& trimmedInput.length &&! tags.includes (trimmedInput)) { e.preventDefault (); setTags (prevState=> [... prevState, trimmedInput]); setInput (''); } if (chave==="Backspace"&&! input.length && tags.length) { e.preventDefault (); const tagsCopy=[... tags]; const poppedTag=tagsCopy.pop (); setTags (tagsCopy); setInput (poppedTag); } };
Isso funciona muito bem, mas há um porém. Quando você pressiona a tecla backspace e tem a última tag no campo de entrada, você pode querer pressionar e segurar a tecla backspace para excluir a tag completamente-mas com a implementação atual, você acabará excluindo rapidamente uma tag após a outra se você não libera a tecla rapidamente.
O comportamento que eu esperaria é excluir os caracteres no campo de entrada e, em seguida, parar sem remover a próxima tag, a menos que o usuário libere a tecla e pressione a tecla Backspace novamente.
A solução para esse problema é trivial. Junto com o evento onKeyDown , também precisamos usar o evento onKeyUp para controlar se um pressionamento de tecla foi liberado ou não. Dessa forma, podemos detectar se o usuário estava pressionando a tecla backspace para limpar o campo de entrada.
Primeiro, precisamos de uma nova variável de estado booleano para alternar quando uma tecla é pressionada e liberada.
const [isKeyReleased, setIsKeyReleased]=useState (false);
Defina isKeyReleased
como false
na função onKeyDown e como true
em onKeyUp .
Então, precisamos usar isKeyReleased
como uma condição para a instrução if da lógica de exclusão da tag. Dessa forma, nós apenas excluímos os caracteres no campo de entrada quando a tecla Backspace é pressionada e mantida.
Abaixo estão as versões finais de ambas as funções.
const onKeyDown=(e)=> { const {chave}=e; const trimmedInput=input.trim (); if (key===','&& trimmedInput.length &&! tags.includes (trimmedInput)) { e.preventDefault (); setTags (prevState=> [... prevState, trimmedInput]); setInput (''); } if (key==="Backspace"&&! input.length && tags.length && isKeyReleased) { const tagsCopy=[... tags]; const poppedTag=tagsCopy.pop (); e.preventDefault (); setTags (tagsCopy); setInput (poppedTag); } setIsKeyReleased (false); }; const onKeyUp=()=> { setIsKeyReleased (true); }
Não se esqueça de atualizar a HTML input tag com onKeyUp handler.
Excluindo uma tag específica
Poder excluir uma tag específica é outro recurso necessário para criar uma boa experiência do usuário. Para implementar isso, precisamos alterar ligeiramente a marcação da tag, adicionando apenas um botão HTML tag.
O manipulador de eventos onClick do botão chama uma função chamada deleteTag
, onde index
de uma tag é passado como um argumento.
{tags.map ((tag, índice)=> ({marcação}))}
A função deleteTag
filtra as tags por seus valores de índice. Como passamos o índice
da tag que queremos excluir, escolhemos todas as tags que não têm a mesma posição de índice na matriz.
const deleteTag=(index)=> { setTags (prevState=> prevState.filter ((tag, i)=> i!==índice)) }
Neste ponto, temos um campo de entrada de tag totalmente funcional, mas obviamente não parece bom. Não entrarei em detalhes de estilo, mas abaixo você pode encontrar um exemplo de arquivo CSS com a seguinte aparência:
.container { display: flex; estouro: rolar; largura: 100%; largura máxima: 100%; padding-left: 14px; borda: sólido cinza de 1 px; raio da borda: 5px; cor preta } .container input { largura: 100%; largura mínima: 50%; fronteira: nenhum; raio da borda: 5px; preenchimento: 14px; padding-left: 14px; } .marcação { display: flex; alinhar-itens: centro; margem: 7px 0; margem direita: 10px; preenchimento: 0 10px; padding-right: 5px; borda: laranja sólido de 1px; raio da borda: 5px; cor de fundo: laranja; espaço em branco: nowrap; cor branca; } .tag button { display: flex; preenchimento: 6px; fronteira: nenhum; cor de fundo: não definida; cursor: ponteiro; cor branca; }
Espero que você tenha achado útil este tutorial sobre a construção de um componente de campo de entrada de tag no React. Obrigado por ler.
A postagem Construindo um componente de campo de entrada de tag para React apareceu primeiro no LogRocket Blog .