React Hook Form é uma das bibliotecas mais populares para lidar com entradas de formulário no ecossistema React. Fazer com que funcione corretamente pode ser complicado se você estiver usando uma biblioteca de componentes, como Material UI.

Neste guia, vamos demonstrar como usar Material UI com React Hook Form. Este tutorial também é útil se você deseja integrar algum outro Biblioteca de IU do React , como Ant Design ou Semantic UI.

Para acompanhar, você já deve ter algum contato com IU de material e React Hook Form . Não vamos nos aprofundar muito em como usar essas bibliotecas. Em vez disso, vamos nos concentrar na integração entre eles.

Para mostrar como usar a IU do Material com o React Hook Form, vamos construir um formulário completo com os componentes de entrada mais usados ​​fornecidos pelo Material IU, incluindo:

Entrada de texto Entrada de rádio Caixa de seleção Data suspensa deslizante

O formulário também terá a funcionalidade de redefinição. Será semelhante a:

Se você é um aluno mais visual, confira o tutorial em vídeo que o acompanha:

Componente de entrada de texto

Vamos começar com um componente de formulário simples. Este componente terá apenas uma entrada de texto.

Para construir este formulário pela abordagem tradicional sem qualquer biblioteca, precisamos lidar com a mudança de entrada separadamente. Também temos que cuidar da funcionalidade de redefinição e validação nós mesmos.

Provavelmente será algo assim:

import TextField from”@ material-ui/core/TextField”; import React, {useState} de”react”; importar {botão, papel} de”@ material-ui/core”; export const FormWithoutHookForm=()=> {const [textValue, setTextValue]=useState (“”); const onTextChange=(e: any)=> setTextValue (e.target.value); const handleSubmit=()=> console.log (textValue); const handleReset=()=> setTextValue (“”); return (

Form Demo

); };

A saída será semelhante a esta:

Aqui, estamos armazenando o valor usando o gancho useState fornecido pelo próprio React:

const [textValue, setTextValue]=useState (“”);

Além disso, estamos definindo o valor da entrada em nossa função onTextChange:

const onTextChange=(e: any)=> setTextValue (e.target.value);

Se olharmos para o componente TextInput fornecido por material-ui, podemos ver que há dois objetos importantes passados ​​para ele: value e onChange. value cuida do valor real da entrada, enquanto onChange determina o que acontece quando a entrada muda. No entanto, usamos este formulário, precisamos cuidar dessas duas coisas.

Configurando o formulário React Hooks

O React Hook Form exporta alguns utilitários do famoso useForm Hook, que você então use dentro de seus componentes de entrada.

Primeiro, importe o gancho useForm:

import {useForm} de”react-hook-form”;

Então, use o Gancho dentro do componente:

const {register}=useForm ();

Uma entrada típica pode ser parecida com esta:

Olhe com atenção aqui: passamos o registro como um valor para o ref do componente de entrada real. Toda a magia acontece nos bastidores.

reactstrap fornece um suporte semelhante chamado innerRef, que pode ser usado para passar em nosso registro para integração perfeita com o react-hook-form.

Infelizmente, este não é o caso quando usamos o Material UI; a biblioteca ainda não fornece nenhum prop semelhante para passar o registro como um valor para o prop ref.

O componente Controller

React Hook Form inclui um componente wrapper chamado Controller para trabalhar bibliotecas de componentes onde você não pode acessar o ref diretamente.

De acordo com o React docs , esta é uma propriedade de renderização-uma função que retorna um elemento React e fornece a capacidade de anexar eventos e valor ao componente.

O esqueleto deste componente Controlador especial é o seguinte:

(WHATEVER_INPUT_WE_WANT)}/>

Vamos analisar o que está acontecendo aqui:

o controle é um prop que obtemos do gancho useForm e passamos para o nome da entrada é como o React Hook Form rastreia o valor de um a entrada de renderização interna é o adereço mais importante; passamos uma função de renderização aqui

A proposta de renderização

A propriedade de renderização do Controlador é a prop mais importante de se entender. A função tem três chaves: field, fieldState e formState. Vamos nos concentrar no campo por enquanto.

O objeto de campo exporta duas coisas (entre outras): valor e onChange. Já vimos que precisamos dessas duas coisas para controlar quase todas as entradas.

Refatorando nosso formulário

Então, vamos ver se o componente Controlador realmente resolve nossos problemas. Usaremos o componente Controller e passaremos o TextInput dentro da função de renderização.

Vamos primeiro extrair o que precisamos do gancho useForm:

const {handleSubmit, reset, control}=useForm ( );

Então, use o componente Controlador na forma desta forma:

import TextField de”@ material-ui/core/TextField”; import React, {useState} de”react”; importar {botão, papel} de”@ material-ui/core”; import {Controller, useForm} de”react-hook-form”; export const FormWithHookForm=()=> {const {handleSubmit, reset, control}=useForm (); const onSubmit=(data: any)=> console.log (data); return (

()}/>

); };

Este formulário funciona exatamente como o anterior. A mágica acontece graças à propriedade do campo da função de renderização fornecida pelo Controlador.

Extraindo um componente para torná-lo reutilizável

Então agora sabemos como usar o componente Controlador do React Formulário de gancho para fazer o formulário funcionar sem qualquer ref. Agora vamos extrair o componente de entrada para um componente separado para que possamos usá-lo em qualquer lugar.

Este componente comum precisará de três adereços de seu pai:

nome, a chave para o controle de entrada que é usado para obter acesso às funcionalidades do rótulo React Hook Form, o rótulo da entrada (opcional) importa TextField de”@ material-ui/core/TextField”; import {Controller} de”react-hook-form”; importar React de”react”; export const FormInputText=({nome, controle, rótulo})=> {return (()}/>); };

Usaremos este componente em nosso formulário da seguinte forma:

import {FormInputText} from”./FormInputTextGood”; export const FormWithHookForm=()=> {//resto são os mesmos que antes de retornar (

) ; };

Agora, o componente é muito mais fácil de entender e reutilizar. Vamos cuidar de algumas outras entradas também.

O componente de entrada de rádio

O segundo componente de entrada mais comum é o rádio. Há um conceito importante a ser lembrado aqui.

Se você usou a IU Radio from Material, você já sabe que precisa do componente RadioGroup como pai e um monte de opções internas, como botões de rádio individuais, como crianças:

import React from”react”; import {FormControl, FormControlLabel, FormLabel, Radio, RadioGroup,} de”@ material-ui/core”; import {Controller, useFormContext} de”react-hook-form”; import {FormInputProps} de”./FormInputProps”; const options=[{label:”Radio Option 1″, value:”1″,}, {label:”Radio Option 2″, value:”2″,},]; export const FormInputRadio: React.FC =({name, control, label})=> {const generateRadioOptions=()=> {return options.map ((singleOption)=> (}/>)); }; return ( {generateRadioOptions ()} )}/>};

O conceito principal é o mesmo aqui. Apenas usamos onChange e o valor do objeto de campo de funções de renderização e passamos para o RadioGroup.

Observe que não usamos o rótulo aqui. Se quiser usar isso, você precisará adicionar os componentes FormControl e FormLabel da interface do usuário do material.

Observe também que usou uma função especial, generateRadioOptions, para gerar as entradas de rádio individuais. Adicionamos as opções como uma constante dentro do componente. Você pode tê-los como adereços ou de qualquer outra forma que achar conveniente.

Suspenso

Quase qualquer formulário precisa de algum tipo de menu suspenso. O código para o componente Dropdown é o seguinte:

import React from”react”; import {FormControl, InputLabel, MenuItem, Select} de”@ material-ui/core”; import {useFormContext, Controller} de”react-hook-form”; importar {FormInputProps} de”./FormInputProps”; opções const=[{rótulo:”Opção suspensa 1″, valor:”1″,}, {rótulo:”Opção suspensa 2″, valor:”2″,},]; export const FormInputDropdown=({name, control, label})=> {const generateSelectOptions=()=> {return options.map ((option)=> {return ( {option.label} );}); }; return (