Introdução
Neste tutorial, vamos explorar o desenvolvimento de uma aplicação de lista de tarefas utilizando TypeScript, React e Redux. A aplicação permitirá que os usuários adicionem, removam e visualizem tarefas, seguindo as melhores práticas de desenvolvimento, incluindo uso de tipagem estática com TypeScript, gerenciamento de estado global com Redux e testes automatizados com Jest. Ao final deste guia, você terá uma aplicação funcional e testada, além de uma compreensão sólida dos padrões usados na construção de aplicações modernas em JavaScript.
Etapas
Configuração do Ambiente de Desenvolvimento
Antes de começar a codificar, precisamos configurar nosso ambiente de desenvolvimento. Certifique-se de ter o Node.js e o npm (Node Package Manager) instalados. Você pode verificar as versões instaladas usando os comandos `node -v` e `npm -v`. Depois, crie um novo projeto utilizando o Create React App com suporte a TypeScript.
commands# Verificar versões instaladas
node -v
npm -v
# Criar um novo projeto React com TypeScript
npx create-react-app my-todo-app --template typescript
# Navegar até o diretório do projeto
cd my-todo-appInstalação das Dependências Redux
Para gerenciar o estado da aplicação, vamos utilizar o Redux. Instale as seguintes bibliotecas: redux, react-redux e @reduxjs/toolkit para facilitar a criação da store e dos slices.
commands# Instalar o Redux e dependências
npm install redux react-redux @reduxjs/toolkitConfiguração da Store Redux
Crie uma pasta chamada `store` dentro do diretório `src`. Dentro dessa pasta, crie o arquivo `store.ts`, onde vamos configurar nossa store Redux.
store/store.tsimport { configureStore } from '@reduxjs/toolkit'; import taskReducer from './taskSlice'; const store = configureStore({ reducer: { tasks: taskReducer } }); export default store;
Criação do Slice de Tarefas
Crie um arquivo chamado `taskSlice.ts` na mesma pasta `store`. Nesse arquivo, definiremos as ações e o estado inicial das nossas tarefas.
store/taskSlice.tsimport { createSlice, PayloadAction } from '@reduxjs/toolkit'; interface Task { id: number; title: string; completed: boolean; } interface TaskState { tasks: Task[]; } const initialState: TaskState = { tasks: [], }; const taskSlice = createSlice({ name: 'tasks', initialState, reducers: { addTask(state, action: PayloadAction<string>) { const newTask: Task = { id: Date.now(), title: action.payload, completed: false, }; state.tasks.push(newTask); }, removeTask(state, action: PayloadAction<number>) { state.tasks = state.tasks.filter(task => task.id !== action.payload); }, toggleTask(state, action: PayloadAction<number>) { const task = state.tasks.find(task => task.id === action.payload); if (task) { task.completed = !task.completed; } } }, }); export const { addTask, removeTask, toggleTask } = taskSlice.actions; export default taskSlice.reducer;
Criação do Componente de Lista de Tarefas
Dentro do diretório `src`, crie uma pasta chamada `components` e adicione um arquivo `TaskList.tsx`. Este componente renderizará a lista de tarefas e permitirá adicionar novas tarefas.
components/TaskList.tsximport React, { useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { addTask, removeTask, toggleTask } from '../store/taskSlice'; const TaskList: React.FC = () => { const [taskInput, setTaskInput] = useState(''); const dispatch = useDispatch(); const tasks = useSelector((state: any) => state.tasks.tasks); const handleAddTask = () => { if (taskInput) { dispatch(addTask(taskInput)); setTaskInput(''); } }; return ( <div> <h2>Lista de Tarefas</h2> <input type="text" value={taskInput} onChange={e => setTaskInput(e.target.value)} placeholder="Adicionar nova tarefa" /> <button onClick={handleAddTask}>Adicionar</button> <ul> {tasks.map(task => ( <li key={task.id} onClick={() => dispatch(toggleTask(task.id))} style={{ textDecoration: task.completed ? 'line-through' : 'none' }}> {task.title} <button onClick={() => dispatch(removeTask(task.id))}>Remover</button> </li> ))} </ul> </div> ); }; export default TaskList;
Integração do Redux no Componente Principal
No arquivo `index.tsx`, vamos integrar a store Redux com o React utilizando o Provider do react-redux.
index.tsximport React from 'react'; import ReactDOM from 'react-dom/client'; import { Provider } from 'react-redux'; import store from './store/store'; import App from './App'; const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement); root.render( <Provider store={store}> <App /> </Provider> );
Criação do Componente Principal
Agora, edite o arquivo `App.tsx` para incluir o componente `TaskList` que criamos anteriormente.
App.tsximport React from 'react'; import TaskList from './components/TaskList'; const App: React.FC = () => { return ( <div> <h1>Aplicação de Lista de Tarefas</h1> <TaskList /> </div> ); }; export default App;
Implementação de Testes Automatizados com Jest
Crie um arquivo `taskSlice.test.ts` na pasta `store`. Neste arquivo, vamos implementar testes para nossas funções do taskSlice utilizando Jest.
store/taskSlice.test.tsimport taskReducer, { addTask, removeTask, toggleTask } from './taskSlice'; describe('taskSlice', () => { it('deve adicionar uma nova tarefa', () => { const initialState = { tasks: [] }; const newState = taskReducer(initialState, addTask('Nova Tarefa')); expect(newState.tasks).toHaveLength(1); expect(newState.tasks[0].title).toBe('Nova Tarefa'); }); it('deve remover uma tarefa', () => { const initialState = { tasks: [{ id: 1, title: 'Tarefa 1', completed: false }] }; const newState = taskReducer(initialState, removeTask(1)); expect(newState.tasks).toHaveLength(0); }); it('deve alternar o status de uma tarefa', () => { const initialState = { tasks: [{ id: 1, title: 'Tarefa 1', completed: false }] }; const newState = taskReducer(initialState, toggleTask(1)); expect(newState.tasks[0].completed).toBe(true); }); });
Executando a Aplicação e os Testes
Para executar a aplicação, utilize o comando `npm start`. Para executar os testes, utilize o comando `npm test` e selecione as opções apropriadas para rodar os testes.
commands# Executar a aplicação
npm start
# Executar os testes
npm test
Conclusão
Neste tutorial, você aprendeu a criar uma aplicação de lista de tarefas utilizando TypeScript, React e Redux, implementando recursos essenciais como adição, remoção e alteração do estado das tarefas. Você também integrou testes automatizados com Jest, garantindo que a lógica da sua aplicação esteja funcionando conforme esperado. Agora você pode expandir essa base, adicionando mais funcionalidades e refinando o design da sua aplicação.