Ao gerenciar estados complexos em um aplicativo Next, as coisas podem ficar complicadas rapidamente. Anzóis tradicionais como useState ajuda com a gestão do estado, mas apresenta um problema de perfuração de propulsão. Prop drill significa passar dados ou funções por vários componentes.

Uma abordagem melhor seria separar sua lógica de gerenciamento de estado dos componentes e atualizar esses estados de qualquer lugar em seu aplicativo. Orientaremos você sobre como usar a API de contexto enquanto criamos um aplicativo de lista de tarefas simples.

Antes de começar sua lista de tarefas

Antes de criar o aplicativo de lista de tarefas, você precisará de:

  • Conhecimento básico de operadores JavaScript modernos e Gancho useState do React.
  • Uma compreensão de como desestruturar arrays e objetos em JavaScript.
  • v16.8 ou posterior instalado em sua máquina local e familiaridade com gerenciadores de pacotes como npm ou fio.

Você pode encontrar o projeto finalizado em GitHub para referência e exploração adicional.

instagram viewer

Compreendendo o estado e o gerenciamento do aplicativo

O estado do aplicativo refere-se à condição atual de um aplicativo em um determinado momento. Isso inclui informações que o aplicativo conhece e gerencia, como entrada do usuário e dados obtidos de um banco de dados ou de uma API (Application Programming Interface).

Para entender o estado do aplicativo, considere os possíveis estados de um aplicativo contador simples. Eles incluem:

  • O estado padrão quando o contador está em zero.
  • Um estado aumentado quando o contador aumenta em um.
  • Um estado diminuído quando o contador reduz em um.
  • Um estado de redefinição quando o contador retorna ao seu estado padrão.

Um componente React pode se inscrever em mudanças de estado. Quando um usuário interage com tal componente, suas ações, como cliques de botão, podem gerenciar atualizações no estado.

Este snippet mostra um aplicativo contador simples, em seu estado padrão, que gerencia o estado com base nas ações de clique:

const [contador, setContador] = useState(0);

retornar (


{counter}</h1>

Configuração e instalação

O repositório do projeto contém duas ramificações: iniciante e contexto. Você pode usar a ramificação inicial como base para construir o projeto ou a ramificação de contexto para visualizar a demonstração final.

Clonando o aplicativo inicial

O aplicativo inicial fornece a IU necessária para o aplicativo final, para que você possa se concentrar na implementação da lógica principal. Abra um terminal e execute o seguinte comando para clonar a ramificação inicial do repositório em sua máquina local:

git clone -b iniciador https://github.com/makeuseofcode/Next.js-CRUD-todo-app.git

Execute o seguinte comando, dentro do diretório do projeto, para instalar as dependências e iniciar seu servidor de desenvolvimento:

fio && fio de desenvolvimento

Ou:

npm i && npm executar dev

Se tudo correr bem, a interface do usuário deve ser exibida em seu navegador:

Implementando a Lógica

A API Context fornece uma maneira de gerenciar e compartilhar dados de estado entre os componentes, sem a necessidade de detalhamento manual.

Passo 1: Criar e Exportar Contexto

Criar uma src/aplicativo/contexto pasta para armazenar o arquivo de contexto e manter o diretório do projeto bem organizado. Dentro desta pasta, crie um todo.context.jsx arquivo que conterá toda a lógica de contexto para o aplicativo.

Importar o criarContexto função do reagir biblioteca e chame-a, armazenando o resultado em uma variável:

importar {criarContexto} de"reagir";
const TodoContext = criarContext();

Em seguida, crie um personalizado useTodoContext gancho que retorna TodoContext em sua forma utilizável.

exportarconst useTodoContext = () => useContext(TodoContext);

Etapa 2: criar e gerenciar estados

Para realizar as ações CRUD (Criar, Ler, Atualizar, Excluir) do aplicativo, você precisará criar os estados e gerenciá-los com o Fornecedor componente.

const TodoContextProvider = ({ crianças }) => {
const [tarefa, setTask] = useState("");
const [tarefas, setTasks] = useState([]);
retornar<TodoContext. Fornecedorvalor={{}}>{crianças}TodoContext. Fornecedor>;
};

exportarpadrão TodoContextProvider;

Pouco antes do retornar declaração, crie um handleTodoInput função que será executada quando o usuário digitar uma tarefa. Esta função então atualiza o tarefa estado.

const handleTodoInput = (entrada) => setTask (entrada);

Adicionar um criarTarefa função que será executada quando um usuário enviar uma tarefa. Esta função atualiza o tarefas state e atribui à nova tarefa um ID aleatório.

const criarTask = (e) => {
e.preventDefault();

setTasks([
{
eu ia: Matemática.trunc(Matemática.aleatório() * 1000 + 1),
tarefa,
},
...tarefas,
]);
};

Criar um atualizarTarefa função que mapeia através do tarefas list e atualiza a tarefa cujo ID corresponde ao ID da tarefa clicada.

const atualizarTask = (id, atualizarTexto) =>
setTasks (tasks.map((t) => (t.id id? { ...t, tarefa: updateText }: t)));

Criar uma deleteTask função que atualiza o tarefas list para que inclua todas as tarefas cujo ID não corresponda ao parâmetro fornecido.

const deleteTask = (eu ia) => setTasks (tasks.filter((t) => t.id !== id));

Etapa 3: adicionar estados e manipuladores ao provedor

Agora que você criou os estados e escreveu o código para gerenciá-los, precisa disponibilizar esses estados e as funções do manipulador para o Fornecedor. Você pode fornecê-los na forma de um objeto, usando o valor propriedade do Fornecedor componente.

retornar (
valor={{
tarefa,
tarefas,
handleTodoInput,
criarTarefa,
atualizarTarefa,
deleteTask,
}}
>
{crianças}
</TodoContext.Provider>
);

Passo 4: Escopo do Contexto

O Fornecedor você criou deve agrupar o componente de nível superior para tornar o contexto disponível para todo o aplicativo. Para fazer isso, edite src/app/page.jsx e embrulhe o Todos componente com o TodoContextProvider componente:


;
</TodoContextProvider>;

Passo 5: Use o Contexto em Componentes

Edite seu src/app/components/Todos.jsx arquivar e desestruturar tarefas, tarefa, handleTodoInput, e criarTarefa através de uma chamada para o useTodoContext função.

const { tarefa, tarefas, handleTodoInput, createTask } = useTodoContext();

Agora, atualize o elemento do formulário para lidar com o evento de envio e alterações no campo de entrada principal:

criarTarefa (e)}>
"todo-entrada" tipo="texto" espaço reservado ="Insira uma tarefa" required value={task} onChange={(e) => handleTodoInput (e.target.value)} />
"enviar-todo" tipo="enviar" valor="Adicionar tarefa" />
</form>

Etapa 6: renderizar tarefas na interface do usuário

Agora você pode usar o aplicativo para criar e adicionar uma tarefa ao tarefas lista. Para atualizar a exibição, você precisará mapear por meio de tarefas e renderizá-los na interface do usuário. Primeiro, crie um src/app/components/Todo.jsx para armazenar um único item de tarefa.

Dentro do src/app/components/Todo.jsx componente, edite ou exclua uma tarefa invocando o atualizarTarefa e deleteTask funções que criamos em src/app/context/todo.context.jsx arquivo.

importar Reagir, { useState } de"reagir";
importar { useTodoContext } de"../context/todo.context";

const Tudo = ({ tarefa }) => {
const { updateTask, deleteTask } = useTodoContext();

// estado isEdit rastreia quando uma tarefa está no modo de edição
const [isEdit, setIsEdit] = useState(falso);

retornar (

"todo-wrapper">


{éEditar? ( <entradatipo="texto"valor={tarefa.tarefa}
onChange={(e) => updateTask (task.id, e.target.value)} /> ):
(<ºnome da classe="tarefa">{tarefa.tarefa}º> )}
"ações">

exportarpadrão Pendência;

Para renderizar o src/app/components/Todo.jsx componente para cada tarefa, entre no src/app/components/Todos.jsx arquivar e mapear condicionalmente através do tarefas logo após o cabeçalho etiqueta de fechamento.

{tarefas && (

{tasks.map((tarefa, eu) => ( <Pendênciachave={eu}tarefa={tarefa} /> ))}
</main>
)}

Teste seu aplicativo em um navegador e confirme se ele fornece o resultado esperado.

Salvando Tarefas no Armazenamento Local

Atualmente, atualizar a página redefinirá as tarefas, descartando as que você criou. Uma maneira de corrigir esse problema é armazenar as tarefas no armazenamento local do navegador.

A API de armazenamento na Web é uma melhoria no armazenamento de cookies, com recursos que melhoram a experiência de usuários e desenvolvedores.