Início Profile Projeto
Avatar de

Livio Lopes de Alvarenga

Projeto de post com comentário utilizando o Nextjs 13 App Router, React, Typescript e Tailwindcss

  • NodeJs
  • TypeScript
  • JavaScript
  • Typescript
  • Nextjs
  • React
  • Tailwind
  • ZodJs
  • EsLint
  • prettier.

Projeto de post com comentário utilizando o Nextjs 13 App Router, React, Typescript e Tailwindcss.

SobreVitrine DevTecnologiasInstalaçõesFuncionalidadesDeployGood habitsAutorLicença

 

react-post-with-comment

💻 Sobre o projeto

🚀 O projeto "Projeto de post com comentário utilizando o Nextjs 13 App Router, React, Typescript e Tailwindcss" é uma aplicação desenvolvida utilizando tecnologias como Next.js, React, TypeScript e Tailwind CSS. O objetivo do projeto é criar um post com comentários, utilizando os conceitos mais importantes do React, como componentização, propriedades, estados, imutabilidade e hooks.

A metodologia mobile first foi utilizada no desenvolvimento da aplicação, visando uma experiência responsiva em dispositivos móveis. Além disso, foram adotadas diversas tecnologias e ferramentas para garantir boas práticas de desenvolvimento, tais como Node.js, ZodJs para validação de dados de entrada, Eslint e Prettier para padronização de código, Dotenv para variáveis de ambiente, Tailwind CSS para estilização, Next.js para renderização do lado do servidor (SSR) e TypeScript para tipagem estática.

O projeto foi implantado na plataforma Vercel.com, que permite hospedar e implantar facilmente aplicações Next.js.

Durante o desenvolvimento, também foi abordado o tema da diferença entre as abordagens de exportação "export default" e "export function" no JavaScript/TypeScript, destacando suas características e flexibilidades na importação de módulos.

Outro tópico abordado foi a diferença entre programação imperativa e programação declarativa. Foram explicados os conceitos e exemplos de cada abordagem, ressaltando a vantagem da programação declarativa no desenvolvimento com React, devido à sua facilidade de leitura, entendimento, manutenção e reutilização.

Além disso, foi discutida a importância de utilizar uma chave (key) única para cada item em uma lista renderizada no React. Foi explicado como o React utiliza essa chave para identificar alterações na lista e como o uso inadequado de uma chave baseada no índice pode levar a problemas de renderização ineficiente e perda de estado.

Por fim, foi abordada a importância das closures e a atualização correta do estado no React. Foram apresentados exemplos demonstrando como o uso da função de atualização de estado (setState) que recebe uma função como argumento garante que sempre trabalhemos com o valor mais atual do estado, evitando problemas de atualização incorreta quando múltiplas atualizações são agendadas na mesma função de manipulação de eventos.

 

issue site Template-Api-Rest-Node-Docker-Prisma total amount of programming languages used in the project most used language in the projects repository size

deploy badge Vercel

 


 

📺 Vitrine Dev

🪧 Vitrine.Dev
Nome Projeto de post com comentário utilizando o Nextjs 13 App Router, React, Typescript e Tailwindcss
🏷️ Tecnologias NodeJs, TypeScript, JavaScript, Typescript, Nextjs, React, Tailwind, ZodJs, EsLint e prettier.

 

🛠 Tecnologias

As seguintes ferramentas foram usadas na construção do projeto

 

Node.js badge TypeScript badge JavaScript badge Next.js badge React badge Tailwind CSS badge ZOD badge vscode download code formatter prettier code standardization eslint


 

⚙️ Instalações

 

Criando projeto NextJs

# Create project nodejs with npm and -y to accept all default options
npx create-next-app@latest

# What is your project named? project-Name
# Would you like to use TypeScript with this project? Yes
# Would you like to use ESLint with this project? Yes
# Would you like to use Tailwind CSS with this project? Yes
# Would you like to use `src/` directory with this project? Yes
# Use App Router (recommended)? Yes
# Would you like to customize the default import alias? No
// Create scripts in package.json
"scripts": {
  "dev": "next dev", // Start development server
  "build": "next build", // Create production build
  "start": "next start", // Start production server
  "lint": "next lint" // Run ESLint
},

Create .nvmrc file with version of NodeJs to use in project  

Configurando ESlint and Prettier

npm install -D @rocketseat/eslint-config # Install Rocketseat ESLint config
npm install -D prettier-plugin-tailwindcss # Install prettier plugin to use TailwindCSS

Edit .eslintrc.json file with extends Rocketseat ESLint config

{
  "extends": ["next/core-web-vitals", "@rocketseat/eslint-config/react"]
}

Create .eslintignore file with all ESLint ignore files

Create prettier.config.js file with plugin prettier-plugin-tailwindcss to use Prettier to format classnames of TailwindCSS

module.exports = {
  plugins: [require("prettier-plugin-tailwindcss")],
};

 

TypeScript architecture

...

 

Others libraries

npm install zod # Install zod to use types in NodeJs and validate data

 

⚙️ Funcionalidades

RF - Requisitos Funcionais

  • Deve ser possível ...;
  • Deve ser possível ...;

RN - Regras de Negócio

  • O usuário não pode ...;
  • O usuário não pode ...;

RNF - Requisitos Não Funcionais

  • Uso de Zod para validação de dados de entrada;
  • Uso de Eslint para padronização de código;
  • Uso de Prettier para padronização de código;
  • Uso de Dotenv para variáveis de ambiente;
  • Uso de TailwindCSS para estilização;
  • Uso de NextJs para SSR;
  • Uso de TypeScript para tipagem estática;
  • Uso de NextJs com App Router para rotas;

 

🧭 Rodando a aplicação (Modo desenvolvimento)

git clone https://github.com/LivioAlvarenga/react-post-with-comment # Clone este repositório
cd react-post-with-comment # Acesse a pasta do projeto no seu terminal/cmd
npm install # Instale as dependências
npm run dev # Execute a aplicação em modo de desenvolvimento, a aplicação será aberta na porta:3000 - acesse http://localhost:3000

# Read the observations in home page

Create .npmrc file with save-exact=true to save exact version of dependencies. Create only if you want to save exact version of dependencies and do this after install all dependencies

Open .gitignore and add files folder, because this folder is to put files of project that is not committed in git

🧭 Rodando a aplicação (Modo produção)

npm run build # Compilar o TypeScript em modo de produção
npm run start # Iniciar o servidor em modo de produção

🧭 Testes

...

 


 

🚀 Deploy

O deploy foi realizado na plataforma Vercel.com.

As variáveis de ambiente configuradas incluem:

  • ...

 

✅ Good Habits

 

❗ 1 - export default function Vs export function

 

Em resumo, a diferença fundamental entre essas duas abordagens de exportação reside na forma como são importadas em outros arquivos. export default function Home() permite um pouco mais de flexibilidade na nomenclatura ao importar, enquanto export function Home() requer que você especifique exatamente o nome da função que está importando.

export default function Home() {}

import MyHome from "./Home";
export function Home() {}

import { Home } from "./Home";

Para garantir esta boa pratica de código, foi instalado o plugin eslint-plugin-import e configurado no arquivo .eslintrc.json. Excluindo os arquivos page.tsx e layout.tsx que no NextJs usa o export default.

"overrides": [
    {
      "files": [
        "**/*.tsx"
      ],
      "excludedFiles": [
        "*page.tsx",
        "*layout.tsx"
      ],
      "plugins": [
        "import"
      ],
      "rules": {
        "import/no-default-export": "error"
      }
    }
  ]

 

❗ 2 - Programação Imperativa Vs Programação Declarativa

 

Programação Imperativa:
A programação imperativa é uma lista detalhada de instruções passo a passo para o computador. É o "como" fazer algo. É semelhante a uma receita de cozinha.

Exemplo: Em JavaScript puro ou jQuery, você pode limpar um campo de entrada de formulário da seguinte maneira:

function handleCrateNewComment(event: FormEvent) {
  event.preventDefault();
  event.target.name.value = "";
}

Nesse exemplo, você está dizendo explicitamente ao navegador para limpar o valor do campo.

Programação Declarativa: A programação declarativa envolve o "o quê" fazer, sem especificar o "como". Você declara o resultado desejado, e o computador descobre como chegar lá.

Exemplo: No React, ao invés de manipular o DOM diretamente, você declara o estado do seu componente e deixa o React cuidar das mudanças no DOM.

function handleCrateNewComment(event: FormEvent) {
  event.preventDefault();

  setComments([...comments, newCommentText]);
  setNewCommentText("");
}

Em resumo, a programação imperativa envolve controle manual e instruções específicas, enquanto a programação declarativa envolve descrever o resultado desejado e deixar o sistema descobrir como realizá-lo.

É uma boa pratica usar sempre que possível a programação declarativa no React, pois ela é mais fácil de ler e entender, e também é mais fácil de manter e reutilizar.

 

❗ 3 - Porque não usar index como key

 

Em React, a propriedade key é muito importante quando se lida com listas de componentes. Essa key ajuda o React a identificar quais itens foram alterados, adicionados ou removidos, o que auxilia o algoritmo de diferenças do React (também conhecido como Reconciliation) a fazer seu trabalho de forma mais eficiente.

Vamos para o exemplo de uma lista de comentários. Cada comentário pode ser um componente, e se você está renderizando uma lista desses componentes, o React precisa de uma maneira de identificar cada um deles unicamente.

Aqui estão algumas situações nas quais o React decide se um componente deve ser renderizado:

  • Quando o estado muda: Se o estado interno de um componente muda, o React vai renderizar esse componente novamente.

  • Quando a propriedade muda: Se as propriedades (props) que um componente recebe mudam, o React renderiza esse componente novamente.

  • Quando um componente pai renderiza: Se um componente pai renderiza, todos os seus componentes filhos também vão renderizar.

Se você usa o índice do item na lista como key, isso pode causar problemas se a ordem dos itens mudar. O React usa a key para decidir se um componente é "o mesmo" que um componente anterior com a mesma key.

Se um item da lista se mover, o React vê que a key em sua posição anterior desapareceu e uma nova apareceu em outra posição. Isso faz com que o React descarte o componente antigo e crie um novo, mesmo que eles representem o mesmo item da lista.

Isso não é apenas ineficiente, mas também pode causar problemas se o componente tiver estado que deve ser preservado.

Portanto, é recomendado usar algo que identifique unicamente cada item da lista como key, como um ID do item, por exemplo. Isso garante que, mesmo se a ordem dos itens mudar, o React ainda saberá que é o mesmo item e reutilizará o componente existente em vez de criar um novo.

{
  comments.map((comment) => <Comment key={comment.id} data={comment} />);
}

No exemplo acima, mesmo se a ordem dos comentários mudar, cada componente Comment continuará correspondendo ao mesmo comentário, pois estamos usando comment.id como key, o que não muda quando a ordem dos comentários muda. Isso resulta em uma renderização mais eficiente.

 

❗ 4 - Entendendo a Atualização do Estado no React e a Importância das Closures

 

const [likeCount, setLikeCount] = useState(0);
function handleLikeComment() {
  setLikeCount((state) => {
    return state + 1;
  });
}

Neste exemplo, estamos usando a versão de setLikeCount que aceita uma função como argumento. Essa função recebe o estado anterior como argumento e retorna o novo estado. Esta é uma abordagem segura quando o novo estado depende do estado anterior, pois garantimos que estamos sempre trabalhando com o valor mais atual do estado.

const [likeCount, setLikeCount] = useState(0);
function handleLikeComment() {
  setLikeCount(likeCount + 1);
}

Neste exemplo, estamos usando a versão de setLikeCount que aceita um valor direto como argumento. Esse valor é calculado com base no valor atual de likeCount no momento em que setLikeCount é chamado. No entanto, se chamarmos setLikeCount duas vezes na mesma função de manipulação de eventos, o estado não será atualizado corretamente.

const [likeCount, setLikeCount] = useState(0);
function handleLikeComment() {
  setLikeCount(likeCount + 1);
  setLikeCount(likeCount + 1);
}

Se tivermos esse código, poderíamos esperar que cada chamada para handleLikeComment incrementasse likeCount em 2. No entanto, isso não acontece. Em vez disso, likeCount é incrementado apenas em 1.

Isso ocorre porque, no momento em que setLikeCount é chamado pela primeira vez, likeCount ainda tem seu valor original. O estado não é atualizado imediatamente quando setLikeCount é chamado; em vez disso, o React "agenda" a atualização para ocorrer mais tarde. Quando setLikeCount é chamado pela segunda vez, likeCount ainda tem o mesmo valor que tinha antes, então estamos basicamente agendando a mesma atualização duas vezes.

Para resolver esse problema e garantir que likeCount seja incrementado corretamente, devemos usar a versão de setLikeCount que aceita uma função como argumento:

const [likeCount, setLikeCount] = useState(0);
function handleLikeComment() {
  setLikeCount((state) => state + 1);
  setLikeCount((state) => state + 1);
}

Agora, cada chamada para handleLikeComment incrementará likeCount em 2, como esperado. Isso ocorre porque, ao usar uma função como argumento para setLikeCount, garantimos que sempre trabalhamos com o valor mais atual do estado, mesmo se múltiplas atualizações forem agendadas na mesma função de manipulação de eventos.


 

🦸 Autor

Olá, eu sou Livio Alvarenga, Engenheiro de Produção | Dev Back-end e Front-end. Sou aficcionado por tecnologia, programação, processos e planejamento. Uni todas essas paixões em uma só profissão. Dúvidas, sugestões e críticas são super bem vindas. Seguem meus contatos.

 

portfólio livio alvarenga perfil LinkedIn livio alvarenga perfil twitter livio alvarenga perfil Instagram livio alvarenga perfil Facebook livio alvarenga perfil YouTube livio alvarenga

perfil vitrinedev livio alvarenga


 

📝 Licença

Este projeto é MIT licensed.

#CompartilheConhecimento