Executando verificação de segurança...
2

Criando seu próprio Hook costumizado no React

Introdução

Pessoal eu estive dando uma estudada (novamente) em Custom Hooks, pois desde que estudei a um tempo atrás, nunca mais coloquei em prática... Resolvi ler novamente a documentação e tirar 100% do recurso, pois eu estive vacilando esse tempo inteiro ao não utilizar.

Então gostaria de compartilhar como criei um Hook simples para validar formulários, bem básico mesmo, na esperança de ajudar quem ainda não sabe, e dê vocês corrigirem quaisquer erros que eu acabei cometendo abaixo :)

A ideia do Hook

EU pensei logo de cara em criar um hook muito simples, para treinar e que fosse útil, não um hook que apenas incrementa algo para ver funcionando. A ideia do hook é validar os campos em tempo real verificando se atende as condições especifícadas.

Primeiro passo

Monte uma estrutura básica de um formulário com dois inputs, um para o nome, e o outro para a senha. Após ter criado a estrutura base no JSX, foi para o arquivo do Hook e comecei a montar a estrutura dele.

O hook

Eu nomei o Hook com o nome de: useValidate(), pois me pareceu mais descritivo assim. Entretanto vendo agora poderia ser useFormValidate(), enfim, depois eu mudo... Ficou assim a estrutura inicial:

    export const useValidate = () => {
    
    }

Depois de ter montado a estrutura incial foi adicionando a lógica. Importei o hook do react, o useState() e criei um state que vai setar os valores do formulário, dessa forma:

    export const useValidate = () => {
    const [formData, setFormData] = useState({
        name: '',
        password: '',
    });
   }

Cada propriedade representa a quantiade de inputs. Lembrando que o nome da propriedade deve ser o mesmo que o atributo name: name="name" e name="password"

Fiz o mesmo processo para os erros utilizando booleanos:

    export const useValidate = () => {
    const [formData, setFormData] = useState({
        name: '',
        password: '',
    });

    const [formError, setFormError] = useState({
        name: false,
        passowrd: false, 
    })
   }

Adicionando um useEffect() responsável por verificar se está tudo certo em tempo real:

    export const useValidate = () => {
    const [formData, setFormData] = useState({
        name: '',
        password: '',
    });

    const [formError, setFormError] = useState({
        name: false,
        passowrd: false, 
    })

    useEffect(() => {
        
        const ErrorObject = {
            name: formData.name.length < 4 || '',
            passowrd: formData.password.length < 8 || ''
        }

        setFormError(ErrorObject)

    }, [formData])
   }

E lógico que não pode faltar a função que vai setar os novoa valores no formData:


export const useValidate = () => {
    const [formData, setFormData] = useState({
        name: '',
        password: '',
    });

    const [formError, setFormError] = useState({
        name: false,
        passowrd: false, 
    })

    useEffect(() => {
        
        const ErrorObject = {
            name: formData.name.length < 4 || '',
            passowrd: formData.password.length < 8 || ''
        }

        setFormError(ErrorObject)

    }, [formData])

    const handleTyping = (e) => {
        const { name, value } = e.target 
        setFormData({...formData, [name]: value})
    }
   }

A função pega os valores retornando pelo o argumento e, que é um objeto DOM, e usa a sintaxe de destruturing para pegar o valor do name do elemento e seu value. Com isso podemos alterar os valores de um input em particular.

Utilizando o setFormDate para copiar o antigo objeto e atualizar as propriedades com os novos valores. O [name] é como um nome de uma propriedade dinâmica, e por isso, que eu disse acima que o nome das propriedades de formData precisa ser o mesmo de name, para corresponder ao input correto e atualizar seus valores. Já o value, que começa inicialmente vazio: '' no formData, atualiza o input correspondente com os novos valores.

E para finalizar, retornei os valores que eu queria:

   'use client'
import { useState, useEffect } from "react"

export const useValidate = () => {
    const [formData, setFormData] = useState({
        name: '',
        password: '',
    });

    const [formError, setFormError] = useState({
        name: false,
        passowrd: false, 
    })

    useEffect(() => {
        
        const ErrorObject = {
            name: formData.name.length < 4 || '',
            passowrd: formData.password.length < 8 || ''
        }

        setFormError(ErrorObject)

    }, [formData])

    const handleTyping = (e) => {
        const { name, value } = e.target 
        setFormData({...formData, [name]: value})
    }

    const ReturnElements = {
        onChange: handleTyping, 
        value: formData,
        booleanForm: formError
    }

    return ReturnElements
}

Pronto, o Hook está completo, e agora só precisa implementar no JSX como fiz aqui:

    'use client'
import { useValidate } from "./hooks/useValidate"

export default function Page() {

    const {value, onChange, booleanForm} = useValidate()

    return (
        <div className="w-screen h-screen flex items-center justify-center bg-zinc-800">
            <form action="" className="bg-zinc-700  flex items-center flex-col text-white justify-center w-[70%] h-[80%] rounded-lg shadow-lg">
                <label htmlFor="name">Name</label>
                <input type="text" value={value.name} onChange={onChange} name="name" className={`${booleanForm.name ? 'border-red-500':'border-zinc-300'}  text-black border rounded-md shadow-md placeholder:text-zinc-500 px-4 py-1`} placeholder="name" id="name"/>
                <label htmlFor="password">Password</label>
                <input type="password" value={value.password} onChange={onChange} name="password" className={`${booleanForm.passowrd ? 'border-red-500':'border-zinc-300'} border text-black  rounded-md shadow-md placeholder:text-zinc-500 p-4 py-1`}placeholder="password" id="password"/>
            </form>
        </div>
    )
}

Observe que eu usei destruturing para quebrar os valores retornados e ficar mais fácil de implementar. Depois disso foi adicionando os valores no JSX. Adicionei o evento onChange, o value e a condicional para retornar uma classe no Tailwind correspondende mudando a cor da bordar para vermelho caso não cumpra os requesitos.

Conlusão

O que acharam da explicação? Deu pra entender a ideia geral? E sobre o hook em si, teria como otimizar mais e melhorar o código? Tornando mais escalável? Comentem!

Carregando publicação patrocinada...