Nesta aula, você aprenderá como criar um formulário interativo para a criação de categorias usando React. O código fornecido ilustra a implementação de um formulário de criação de categorias, onde os usuários podem inserir o nome da categoria e selecionar se ela está ativa ou não.
Durante a aula, você aprenderá sobre os seguintes tópicos:
- Configuração do ambiente de desenvolvimento React.
- Criação de componentes reutilizáveis, como
BoxCreateItem
,FormControl
eCheckbox
. - Utilização de hooks personalizados, como
useCreateCategory
, para gerenciar o estado do formulário e suas interações. - Validação de dados do formulário utilizando
formState.errors
. - Manipulação de eventos e atualização de estado utilizando
register
esetActive
. - Envio do formulário e tratamento de ações utilizando
handleSubmit
ehandleCreateCategory
. - Navegação entre rotas utilizando
cancelRoute
.
Ao final da aula, você terá adquirido conhecimentos práticos sobre como criar formulários interativos no React, além de ter uma compreensão mais sólida sobre o desenvolvimento de componentes reutilizáveis e o uso de hooks personalizados.
O vídeo dessa aula está publicada no bootcamp CrazyStack, se você ainda não garantiu sua vaga clique aqui
O código apresentado refere-se à implementação de um formulário de criação de categoria usando React. Vamos analisar detalhadamente cada parte do código:
- Importações de dependências:
import { CategoryProps } from "entidades/category";
import { useCreateCategory } from "./createCategory.hook";
import { BoxCreateItem, FormControl, Checkbox, GridForm } from "shared/ui";
Nesta seção, são importadas as dependências necessárias para a implementação do formulário. Isso inclui a definição de CategoryProps
, um hook personalizado useCreateCategory
para gerenciar o estado do formulário, além de componentes reutilizáveis como BoxCreateItem
, FormControl
, Checkbox
e GridForm
do pacote shared/ui
.
- Componente
CreateCategoryForm
:
export const CreateCategoryForm = () => {
const { formState, register, handleSubmit, handleCreateCategory, active, setActive } =
useCreateCategory();
return (
// Conteúdo do formulário
);
};
Aqui, temos a definição do componente CreateCategoryForm
, que é uma função de componente sem parâmetros. No interior da função, é feita a desestruturação dos valores retornados pelo useCreateCategory
hook. Esses valores incluem formState
para gerenciar o estado do formulário, register
para registrar campos do formulário, handleSubmit
para lidar com o envio do formulário, handleCreateCategory
para executar a ação de criação da categoria, active
para controlar o estado do checkbox "Ativo" e setActive
para atualizar o estado do checkbox.
- Componente
BoxCreateItem
:
<BoxCreateItem
onSubmit={handleSubmit(handleCreateCategory)}
title={"Createar categoria"}
isLoadingSaveButton={formState.isSubmitting}
cancelRoute={"/categorys/1"}
>
// Conteúdo interno do BoxCreateItem
</BoxCreateItem>
Neste trecho, o componente BoxCreateItem
é renderizado. Ele envolve todo o conteúdo do formulário e possui propriedades que definem o comportamento e a aparência do componente. As propriedades incluem onSubmit
, que define a função a ser chamada ao enviar o formulário, title
, que define o título exibido no cabeçalho do componente, isLoadingSaveButton
, que indica se o botão de salvar está em estado de carregamento, e cancelRoute
, que define a rota para onde o usuário será redirecionado ao cancelar o formulário.
- Componente
GridForm
:
<GridForm>
// Conteúdo interno do GridForm
</GridForm>
Dentro do componente BoxCreateItem
, temos o componente GridForm
, que é usado para organizar os campos do formulário em uma grade. Ele envolve os campos do formulário e fornece uma estrutura visual agradável.
- Componente
FormControl
:
<FormControl
label="Nome da categoria"
error={formState.errors.name}
{...register("name")}
/>
Aqui, temos o componente FormControl
, que representa um campo de formulário. Ele recebe propriedades como label
, que define o rótulo exibido ao lado do campo, error
, que exibe mensagens de erro caso ocorram validações inválidas, e {...register("name")}
, que registra o campo "name" no formulário para ser controlado pelo useCreateCategory
hook.
- Componente
Checkbox
:
<Checkbox
label="Ativo"
colorScheme="green"
isChecked={active}
onChange={(e) => {
e.preventDefault();
setActive(e.target.checked);
}}
/>
Por fim, temos o componente Checkbox
, que representa uma caixa de seleção. Ele recebe propriedades como label
, que define o texto exibido ao lado da caixa de seleção, colorScheme
, que define o esquema de cores do componente, isChecked
, que indica se a caixa de seleção está marcada ou não, e onChange
, que define a função a ser chamada quando o estado do checkbox é alterado.
Esse código apresenta um exemplo prático de como criar um formulário de criação de categoria interativo utilizando React e componentes reutilizáveis. Com ele, é possível coletar informações do usuário, validar os campos e executar a ação de criação da categoria.
CreateCategoryForm (código final)
import { CategoryProps } from "entidades/category";
import { useCreateCategory } from "./createCategory.hook";
import { BoxCreateItem, FormControl, Checkbox, GridForm } from "shared/ui";
export const CreateCategoryForm = () => {
const { formState, register, handleSubmit, handleCreateCategory, active, setActive } =
useCreateCategory();
return (
<BoxCreateItem
onSubmit={handleSubmit(handleCreateCategory)}
title={"Createar categoria"}
isLoadingSaveButton={formState.isSubmitting}
cancelRoute={"/categorys/1"}
>
<GridForm>
<FormControl
label="Nome da categoria"
error={formState.errors.name}
{...register("name")}
/>
<Checkbox
label="Ativo"
colorScheme="green"
isChecked={active}
onChange={(e) => {
e.preventDefault();
setActive(e.target.checked);
}}
/>
</GridForm>
</BoxCreateItem>
);
};
Veja o código a seguir:
CreateCategory Lib (código final)
import { SubmitHandler, useForm } from "react-hook-form";
import * as yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";
export type CreateCategoryFormData = {
name: string;
active?: boolean;
};
export type SubmitCreateCategoryHandler = SubmitHandler<CreateCategoryFormData>;
export const createCategoryFormSchema = yup.object().shape({
name: yup.string().required("Nome é obrigatório"),
});
export const useCreateCategoryLib = () => {
const formProps = useForm<CreateCategoryFormData>({
resolver: yupResolver(createCategoryFormSchema),
defaultValues: {
name: "",
},
});
return { ...formProps };
};
O código apresentado refere-se a uma biblioteca (CreateCategory Lib
) que contém funções e esquemas de validação para o formulário de criação de categoria. Vamos analisar cada parte do código em detalhes:
- Importações de dependências:
import { SubmitHandler, useForm } from "react-hook-form";
import * as yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";
Nesta seção, são importadas as dependências necessárias para o funcionamento da biblioteca. Isso inclui o useForm
e SubmitHandler
do pacote react-hook-form
para gerenciar o estado e lidar com o envio do formulário, o yup
para definir os esquemas de validação e o yupResolver
para resolver os esquemas de validação no useForm
.
- Tipos e interfaces:
export type CreateCategoryFormData = {
name: string;
active?: boolean;
};
export type SubmitCreateCategoryHandler = SubmitHandler<CreateCategoryFormData>;
Nesta seção, são definidos os tipos utilizados pela biblioteca. CreateCategoryFormData
representa os dados do formulário de criação de categoria, contendo um campo name
do tipo string
e um campo opcional active
do tipo boolean
. SubmitCreateCategoryHandler
é um tipo que representa a função de manipulação do envio do formulário.
- Esquema de validação:
export const createCategoryFormSchema = yup.object().shape({
name: yup.string().required("Nome é obrigatório"),
});
Aqui, é definido o esquema de validação utilizando o yup
. O esquema createCategoryFormSchema
é um objeto que especifica as regras de validação para o campo name
. Neste caso, é definido que o campo é uma string e é obrigatório, caso contrário, será exibida a mensagem de erro "Nome é obrigatório".
- Hook personalizado
useCreateCategoryLib
:
export const useCreateCategoryLib = () => {
const formProps = useForm<CreateCategoryFormData>({
resolver: yupResolver(createCategoryFormSchema),
defaultValues: {
name: "",
},
});
return { ...formProps };
};
Aqui, é definido o hook personalizado useCreateCategoryLib
. Esse hook retorna um objeto contendo as propriedades do formulário e as funções relacionadas. Dentro do hook, é utilizado o useForm
para inicializar o estado do formulário. São passados dois argumentos para o useForm
: o resolver
que utiliza o yupResolver
para resolver o esquema de validação definido anteriormente e o defaultValues
que define os valores iniciais do formulário, no caso, apenas o campo name
vazio.
Ao chamar o useCreateCategoryLib
em um componente, você terá acesso a todas as propriedades e funções do formulário, como o estado do formulário (formState
), o registro de campos (register
), a função de envio do formulário (handleSubmit
) e outras propriedades relacionadas ao estado do formulário.
Essa biblioteca facilita a criação e validação do formulário de criação de categoria, fornecendo uma estrutura sólida e consistente para a manipulação dos dados e validação dos campos.
CreateCategory Hook
Veja o código da hook:
import { useUi } from "shared/libs";
import {
CreateCategoryFormData,
SubmitCreateCategoryHandler,
useCreateCategoryLib,
} from "./createCategory.lib";
import { useRouter } from "next/router";
import { api } from "shared/api";
import { useMutation } from "@tanstack/react-query";
import { useState } from "react";
export const useCreateCategory = () => {
const { showModal } = useUi();
const router = useRouter();
const [active, setActive] = useState(false);
const createCategory = useMutation(async (category: CreateCategoryFormData) => {
try {
const { data } = await api.post("/category/add", {
...category,
});
if (!data) {
showModal({
content: "Ocorreu um erro inesperado no servidor, tente novamente mais tarde",
title: "Erro no servidor",
type: "error",
});
return;
}
showModal({
content:
"Categoria criada com sucesso, você será redirecionado para a lista de categorias",
title: "Sucesso",
type: "success",
});
router.push("/categorys/1");
return data;
} catch (error) {
showModal({
content: "Ocorreu um erro inesperado no servidor, tente novamente mais tarde",
title: "Erro no servidor",
type: "error",
});
}
}, {});
const { register, handleSubmit, formState } = useCreateCategoryLib();
const handleCreateCategory: SubmitCreateCategoryHandler = async (
values: CreateCategoryFormData
) => {
await createCategory.mutateAsync({ ...values, active });
};
return { formState, register, handleSubmit, handleCreateCategory, active, setActive };
};
O código apresentado é um hook personalizado chamado useCreateCategory
, que contém a lógica e funcionalidade para criar uma nova categoria. Vamos analisar cada parte do código em detalhes:
- Importações de dependências:
import { useUi } from "shared/libs";
import {
CreateCategoryFormData,
SubmitCreateCategoryHandler,
useCreateCategoryLib,
} from "./createCategory.lib";
import { useRouter } from "next/router";
import { api } from "shared/api";
import { useMutation } from "@tanstack/react-query";
import { useState } from "react";
Nesta seção, são importadas as dependências necessárias para o funcionamento do hook. Isso inclui useUi
para exibir modais, CreateCategoryFormData
e SubmitCreateCategoryHandler
do arquivo createCategory.lib
para lidar com os tipos e manipulação do formulário, useRouter
para obter o objeto de roteamento do Next.js, api
para fazer chamadas à API e useMutation
do pacote react-query
para gerenciar a mutação dos dados.
- Hook personalizado
useCreateCategory
:
export const useCreateCategory = () => {
const { showModal } = useUi();
const router = useRouter();
const [active, setActive] = useState(false);
const createCategory = useMutation(async (category: CreateCategoryFormData) => {
// Lógica de criação de categoria
}, {});
const { register, handleSubmit, formState } = useCreateCategoryLib();
const handleCreateCategory: SubmitCreateCategoryHandler = async (
values: CreateCategoryFormData
) => {
// Função de manipulação do envio do formulário
};
return { formState, register, handleSubmit, handleCreateCategory, active, setActive };
};
Aqui, é definido o hook personalizado useCreateCategory
. Esse hook retorna um objeto contendo as propriedades e funções relacionadas à criação de categoria. Vamos analisar cada parte:
const { showModal } = useUi();
: Aqui, é desestruturado oshowModal
douseUi
, que é um hook utilizado para exibir modais na interface.const router = useRouter();
: Aqui, é utilizado o hookuseRouter
do Next.js para obter o objeto de roteamento, que permite redirecionar o usuário após a criação da categoria.const [active, setActive] = useState(false);
: Aqui, é utilizado o hookuseState
para gerenciar o estado do campoactive
, que representa se a categoria está ativa ou não. O valor inicial é definido comofalse
.const createCategory = useMutation(async (category: CreateCategoryFormData) => { ... }, {});
: Aqui, é utilizado ouseMutation
do pacotereact-query
para criar uma mutação assíncrona. A função de mutação é uma função assíncrona que recebe os dados da categoria como argumento e realiza a lógica de criação da categoria. É feita uma chamada à API utilizandoapi.post
e, em seguida, é exibido um modal de sucesso ou erro dependendo do resultado da chamada. Por fim, a funçãorouter.push
é utilizada para redirecionar o usuário para a lista de categorias. O objeto vazio{}
passado como segundo argumento é opcional e permite a configuração de op
ções adicionais para a mutação.
const { register, handleSubmit, formState } = useCreateCategoryLib();
: Aqui, é utilizado o hookuseCreateCategoryLib
importado anteriormente para obter as propriedades e funções relacionadas ao formulário de criação de categoria.const handleCreateCategory: SubmitCreateCategoryHandler = async (values: CreateCategoryFormData) => { ... };
: Aqui, é definida a funçãohandleCreateCategory
que será chamada quando o formulário for enviado. Essa função recebe os valores do formulário como argumento e chama a função de mutaçãocreateCategory.mutateAsync
para criar a categoria com os valores fornecidos e o estadoactive
.return { formState, register, handleSubmit, handleCreateCategory, active, setActive };
: Por fim, são retornadas as propriedades e funções necessárias para o componente que utilizará o hookuseCreateCategory
.
Esse hook personalizado encapsula a lógica de criação de categoria, facilitando o uso e a reutilização em diferentes componentes, fornecendo as funções e estados necessários para manipular o formulário de criação de categoria, exibir modais e redirecionar o usuário após a criação da categoria.
CategoryCreatePage
Por fim temos o código da página que chama esse trambolho todo:
import { Box, Head } from "shared/ui";
import { CategoryProps } from "entidades/category";
import { CreateCategoryForm } from "features/category/create";
export const CategoryCreatePage = () => {
return (
<>
<Head
title={"Belezix Admin | Categorias"}
description="Página de criação de categorias do painel de Admin Belezix"
/>
<Box flex="1" borderRadius={8} bg="purple.800" p="8">
<CreateCategoryForm />
</Box>
</>
);
};
O código apresentado define um componente chamado CategoryCreatePage
que representa a página de criação de categorias. Vamos analisar cada parte do código em detalhes:
- Importações de dependências:
import { Box, Head } from "shared/ui";
import { CategoryProps } from "entidades/category";
import { CreateCategoryForm } from "features/category/create";
Nesta seção, são importadas as dependências necessárias para o funcionamento da página. Isso inclui componentes como Box
e Head
do pacote "shared/ui" para estruturar a página e definir o título e descrição, além de CategoryProps
do arquivo "entidades/category" para lidar com os tipos relacionados a categoria, e CreateCategoryForm
do arquivo "features/category/create" que é o formulário de criação de categoria.
- Componente
CategoryCreatePage
:
export const CategoryCreatePage = () => {
return (
<>
<Head
title={"Belezix Admin | Categorias"}
description="Página de criação de categorias do painel de Admin Belezix"
/>
<Box flex="1" borderRadius={8} bg="purple.800" p="8">
<CreateCategoryForm />
</Box>
</>
);
};
Aqui, é definido o componente CategoryCreatePage
que representa a página de criação de categorias. Esse componente renderiza o conteúdo principal da página, incluindo o cabeçalho e o formulário de criação de categoria.
<Head ... />
: O componenteHead
é utilizado para definir as meta tags do documento HTML, como o título e a descrição da página. Neste caso, o título é definido como "Belezix Admin | Categorias" e a descrição é definida como "Página de criação de categorias do painel de Admin Belezix".<Box ... />
: O componenteBox
é utilizado para criar uma caixa retangular que envolve o conteúdo da página. Ele define algumas propriedades comoflex
,borderRadius
,bg
ep
para estilizar a caixa. No exemplo, a caixa possui uma flexibilidade de 1, um raio de borda de 8 pixels, uma cor de fundo roxa escura (purple.800) e um espaçamento interno de 8 pixels.<CreateCategoryForm />
: O componenteCreateCategoryForm
é importado e renderizado dentro da caixa. Ele representa o formulário de criação de categoria, permitindo que o usuário insira os dados necessários para criar uma nova categoria.
Em resumo, o componente CategoryCreatePage
representa a página de criação de categorias. Ele inclui um cabeçalho com título e descrição, e renderiza o formulário de criação de categoria dentro de uma caixa estilizada. Isso fornece uma estrutura básica para a página e possibilita a criação de novas categorias no sistema.
Resumindo
Nesta aula, exploramos o desenvolvimento de uma funcionalidade de gerenciamento de categorias em um sistema de administração. Ao longo da aula, abordamos diferentes aspectos do desenvolvimento, desde a criação dos componentes e formulários até a integração com APIs e tratamento de erros.
Começamos entendendo a estrutura básica da funcionalidade de gerenciamento de categorias, identificando as principais entidades envolvidas, como CategoryProps
. Em seguida, discutimos a criação do formulário de edição de categorias, detalhando os componentes EditCategoryForm
, EditCategoryLib
e EditCategoryHook
. Esses componentes foram responsáveis por gerenciar o estado do formulário, a validação dos dados e a comunicação com a API para atualização da categoria.
Além disso, também exploramos o desenvolvimento do formulário de criação de categorias, utilizando os componentes CreateCategoryForm
, CreateCategoryLib
e CreateCategoryHook
. Esses componentes seguiram uma estrutura semelhante ao formulário de edição, porém com a funcionalidade de criação de novas categorias.
Para garantir uma experiência amigável ao usuário, abordamos o tratamento de erros durante as requisições à API, exibindo mensagens de erro adequadas em caso de falhas. Utilizamos o componente showModal
do pacote "shared/libs" para exibir essas mensagens.
Além disso, também discutimos o roteamento entre as páginas, utilizando o useRouter
do pacote "next/router" para redirecionar o usuário para a lista de categorias após a criação ou atualização de uma categoria.
Durante a aula, aprendemos sobre a utilização de bibliotecas populares como react-hook-form
e yup
para facilitar o gerenciamento de formulários e a validação dos dados. Também exploramos a biblioteca react-query
para facilitar a comunicação com a API e gerenciar o estado dos dados.
Ao final da aula, tivemos a oportunidade de criar uma página de criação de categorias, utilizando os componentes desenvolvidos anteriormente e integrando-os em uma página completa.
Através dessa aula, expandimos nossos conhecimentos sobre o desenvolvimento de funcionalidades complexas em aplicações React. Aprendemos sobre a estruturação de componentes, gerenciamento de estado, integração com APIs e tratamento de erros. Essas habilidades serão valiosas para o desenvolvimento de futuros projetos.
Parabéns pelo seu progresso até aqui! Agora você está pronto para aplicar esses conhecimentos em seus próprios projetos e continuar aprimorando suas habilidades como desenvolvedor React.
Desafio do Doido
Desafio Prático: Implementar a funcionalidade de exclusão de categorias
Agora que você já está familiarizado com a funcionalidade de criação e edição de categorias, vamos propor um desafio para você aprimorar ainda mais o código existente.
Neste desafio, você deverá implementar a funcionalidade de exclusão de categorias. Para isso, siga as etapas abaixo:
Crie um novo componente chamado
DeleteCategoryButton
dentro da pastafeatures/category/delete
. Esse componente será responsável por exibir um botão de exclusão de categoria.No componente
DeleteCategoryButton
, adicione uma prop chamadacategoryId
para receber o ID da categoria que será excluída.No componente
DeleteCategoryButton
, utilize o componenteAlertDialog
do pacoteshared/ui
para exibir um diálogo de confirmação antes de excluir a categoria. O diálogo deve exibir uma mensagem de confirmação, como "Tem certeza que deseja excluir esta categoria?". O usuário terá a opção de confirmar ou cancelar a exclusão.No componente
DeleteCategoryButton
, utilize ouseMutation
do pacote@tanstack/react-query
para realizar a exclusão da categoria. Ao confirmar a exclusão, faça uma requisição DELETE para a API, passando o ID da categoria a ser excluída.Trate os possíveis cenários de sucesso e erro durante a exclusão da categoria. Utilize o
showModal
do pacoteshared/libs
para exibir mensagens de sucesso ou erro ao usuário.Atualize o componente
EditCategoryForm
para incluir o componenteDeleteCategoryButton
logo abaixo do formulário de edição. Passe ocategoryId
da categoria atual como prop para o componenteDeleteCategoryButton
.Na página
CategoryEditPage
, importe o componenteDeleteCategoryButton
e passe ocategoryId
para o componente.Na página
CategoryCreatePage
, adicione um botão de cancelar que redirecione o usuário de volta para a lista de categorias. Utilize ouseRouter
do pacotenext/router
para realizar o redirecionamento.
Após concluir o desafio, você terá implementado a funcionalidade de exclusão de categorias, permitindo que o usuário delete uma categoria existente. Isso proporcionará uma experiência mais completa e robusta para o gerenciamento de categorias em seu sistema de administração.
Lembre-se de testar cuidadosamente sua implementação e garantir que todas as funcionalidades estejam funcionando corretamente. Boa sorte e divirta-se codificando!