Melhorando a Experiência do Usuário com um Componente de Entrada Numérica em React

Em desenvolvimento web, especialmente para aplicações que exigem interação constante com dados numéricos, proporcionar uma experiência de usuário fluida e livre de erros é crucial. Um Componente React de input numérico bem projetado não só facilita a interação do usuário, mas também garante que os dados inseridos sejam válidos e formatados corretamente. Este artigo explora um componente React chamado CustomNumberInput, projetado para lidar com inputs numéricos de forma eficiente e melhorar a experiência do usuário.

O componente CustomNumberInput é um campo de input customizado que permite aos usuários inserir números, incluindo valores decimais e negativos. Ele assegura que os dados inseridos sigam regras de formatação específicas, como o número máximo de dígitos inteiros e decimais. Além disso, ele automaticamente lida com a validação e formatação dos valores inseridos, reduzindo a probabilidade de erros e melhorando a usabilidade.

Um exemplo rápido de como você pode usar o componente CustomNumberInput em sua aplicação:

“`javascript
import { CustomNumberInput } from ‘./CustomNumberInput’;

function App() {
const handleNumberChange = (value: string | null) => {
console.log(“Entered value:”, value);
};

return (

);
}

export default App;
“`

Neste exemplo, o Componente React de input numérico CustomNumberInput é usado para permitir que os usuários insiram um número com até 5 dígitos inteiros e 2 dígitos decimais. A prop onChange é usada para lidar com o valor inserido, que é registrado no console.

## Principais Características do Componente React de Input Numérico

O componente CustomNumberInput oferece diversas funcionalidades importantes para garantir a qualidade e a usabilidade dos dados inseridos.

1. Formatação de Números: O componente garante que os números inseridos sejam formatados corretamente, incluindo o tratamento de sinais negativos e positivos, bem como separadores decimais.
2. Validação de Input: Apenas caracteres numéricos, sinais de mais e menos, e separadores decimais são permitidos. Isso impede que os usuários insiram caracteres inválidos.
3. Controle de Dígitos: O componente permite que você defina o número máximo de dígitos inteiros e decimais que podem ser inseridos, o que é útil para aplicações que exigem precisão numérica.
4. Tratamento de Eventos: O componente lida com eventos de teclado (onKeyDown) e de mudança (onChange) para garantir que o input do usuário seja validado e formatado em tempo real.

### Lógica do Componente e Formatação de Valor

A função formatValue é o núcleo do componente. Ela formata o valor inserido pelo usuário de acordo com as regras definidas. Aqui está um resumo do que ela faz:

* Remoção de Caracteres Inválidos: Utiliza uma expressão regular para remover qualquer caractere que não seja um dígito, um sinal de mais ou menos, ou um separador decimal.

“`javascript
let formatted = input.replace(/[^\d-+,.]/, “”)
“`

* Tratamento de Sinais Negativos e Positivos: Assegura que o sinal negativo esteja corretamente posicionado e que sinais positivos não afetem o valor final.

“`javascript
if (formatted.includes(“-“)) {
formatted = formatted.replace(/-/g, “”)
formatted = formatted.startsWith(“-“) ? formatted : `-${formatted}`
}
“`

* Tratamento de Separadores Decimais: Converte qualquer separador decimal (ponto ou vírgula) em um ponto decimal padrão e limita o número de dígitos decimais com base na precisão definida.

“`javascript
if (formatted.includes(“.”) || formatted.includes(“,”)) {
formatted = formatted.replace(“.”, DECIMAL_SEPARATOR)
formatted = formatted.replace(“,”, DECIMAL_SEPARATOR)

const [intPart, …rest] = formatted.split(DECIMAL_SEPARATOR)
const decPart = rest.join(“”)

const limitedDecPart = decPart.slice(0, decimalPrecision.decimalDigits)
const formattedIntPart = !intPart || intPart === “-” ? `0${intPart}` : intPart

formatted = `${formattedIntPart}${DECIMAL_SEPARATOR}${limitedDecPart}`
}
“`

* Limitação de Dígitos Inteiros: Limita o número de dígitos inteiros que podem ser inseridos, garantindo que o limite definido não seja excedido.

“`javascript
const isNegative = formatted.startsWith(“-“)
const digits = isNegative ? formatted.slice(1) : formatted
if (digits.length > decimalPrecision.integerDigits) {
formatted = isNegative
? `-${digits.slice(0, decimalPrecision.integerDigits)}`
: digits.slice(0, decimalPrecision.integerDigits)
}
“`

### Tratamento de Eventos de Teclado

A função handleKeyDown garante que apenas teclas específicas relacionadas ao input numérico sejam permitidas. Isso inclui teclas de navegação (como setas esquerda e direita), teclas de edição (como Backspace e Delete), e caracteres numéricos. Se o usuário tentar inserir um caractere não permitido, o evento é prevenido, e o caractere não aparece no campo de input.

“`javascript
const handleKeyDown = (e: React.KeyboardEvent) => {
const allowedKeys = [
“Backspace”, “Delete”, “ArrowLeft”, “ArrowRight”,
“Tab”, “Home”, “End”, “-“, “+”, “.”, “,”, “0”,
“1”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, “9”
]

if (!allowedKeys.includes(e.key)) {
e.preventDefault()
} else if (valueInput.includes(DECIMAL_SEPARATOR) && (e.key === “.” || e.key === “,”)) {
e.preventDefault()
}
}
“`

### Tratamento de Mudanças

A função handleChange é acionada sempre que o usuário modifica o valor do campo de input. Esta função chama formatValue para formatar o valor inserido e, em seguida, atualiza o estado do componente com o valor formatado. Além disso, notifica o componente pai (através da prop onChange) do novo valor, permitindo uma integração perfeita com outros componentes.

“`javascript
const handleChange = (e: React.ChangeEvent) => {
const newValue = formatValue(e.target.value)
setValueInput(newValue)
onChange?.(newValue === ” ? null : newValue)
}
“`

O componente CustomNumberInput foi criado para melhorar a experiência do usuário ao inserir números em uma aplicação. Ao lidar automaticamente com a validação e formatação, ele reduz a carga cognitiva sobre o usuário e minimiza erros de input. Isso é especialmente útil em contextos financeiros, científicos ou qualquer outro onde a precisão numérica é crítica. Se você busca outras ferramentas, veja como iniciar seu primeiro projeto de IA com o método RICE: alcance, impacto, confiança e esforço.

Você pode ajustar o número de dígitos inteiros e decimais permitidos, e pode estender sua funcionalidade para atender a necessidades específicas. Usuários da Xiaomi poderão usar iMessage em breve.

Aqui está o código completo para o componente CustomNumberInput:

“`javascript
import * as React from “react”
import { type ClassValue, clsx } from “clsx”;
import { twMerge } from “tailwind-merge”;

type DecimalPrecision = {
integerDigits: number
decimalDigits: number
}

export interface CustomNumberInputProps
extends Omit, ‘onChange’> {
className?: string,
decimalPrecision?: DecimalPrecision
onChange?: (value: string | null) => void
}

const DEFAULT_PRECISION: DecimalPrecision = {
integerDigits: 10,
decimalDigits: 2
}

const DECIMAL_SEPARATOR = “.”

const CustomNumberInput = React.forwardRef(
({
className,
decimalPrecision = DEFAULT_PRECISION,
onChange,
…props
}, ref) => {
const [valueInput, setValueInput] = React.useState(“”)

const formatValue = React.useCallback((input: string): string => {
let formatted = input.replace(/[^\d-+,.]/, “”)

if (formatted.includes(“-“)) {
formatted = formatted.replace(/-/g, “”)
formatted = formatted.startsWith(“-“) ? formatted : `-${formatted}`
}

if (formatted.includes(“+”)) {
formatted = formatted.replace(/-/g, “”)
formatted = formatted.replace(/\+/g, “”)
}

if (formatted.includes(“.”) || formatted.includes(“,”)) {
formatted = formatted.replace(“.”, DECIMAL_SEPARATOR)
formatted = formatted.replace(“,”, DECIMAL_SEPARATOR)

const [intPart, …rest] = formatted.split(DECIMAL_SEPARATOR)
const decPart = rest.join(“”)

const limitedDecPart = decPart.slice(0, decimalPrecision.decimalDigits)
const formattedIntPart = !intPart || intPart === “-” ? `0${intPart}` : intPart

formatted = `${formattedIntPart}${DECIMAL_SEPARATOR}${limitedDecPart}`
} else {
const isNegative = formatted.startsWith(“-“)
const digits = isNegative ? formatted.slice(1) : formatted
if (digits.length > decimalPrecision.integerDigits) {
formatted = isNegative
? `-${digits.slice(0, decimalPrecision.integerDigits)}`
: digits.slice(0, decimalPrecision.integerDigits)
}
}

return formatted
}, [decimalPrecision])

const handleKeyDown = (e: React.KeyboardEvent) => {
const allowedKeys = [
“Backspace”, “Delete”, “ArrowLeft”, “ArrowRight”,
“Tab”, “Home”, “End”, “-“, “+”, “.”, “,”, “0”,
“1”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, “9”
]

if (!allowedKeys.includes(e.key)) {
e.preventDefault()
} else if (valueInput.includes(DECIMAL_SEPARATOR) && (e.key === “.” || e.key === “,”)) {
e.preventDefault()
}
}

const handleChange = (e: React.ChangeEvent) => {
const newValue = formatValue(e.target.value)
setValueInput(newValue)
onChange?.(newValue === ” ? null : newValue)
}

const cn = (…inputs: ClassValue[]) => {
return twMerge(clsx(inputs));
}

return (

)
}
)

CustomNumberInput.displayName = “CustomNumberInput”

export { CustomNumberInput }
“`

Este conteúdo foi auxiliado por Inteligência Artificial, mas escrito e revisado por um humano.

Via Dev.to

Leave a Comment

Exit mobile version