INICIO

Este procedimento deve ser realizado somente se você possuir uma branch remota no repositório do que esta sendo apresentado. Caso não possua clique em next.

Guia de Configuração e Execução do Projeto

Siga o passo a passo abaixo para clonar, configurar o ambiente com Git Flow e executar o projeto localmente.

1. Clonar o e acessar o repositório

git clone <endereço-remoto-repositorio>
cd nome do repositório

2. Verificar branches locais

git branch

3. Verificar branches remotas

git branch -a

4. Inicializar a estrutura do Git Flow

Inicia a estrutura do Git Flow no projeto e muda automaticamente para a branch develop:

git flow init

Atenção (PC da Instituição): Caso o Git Flow não esteja instalado no Windows, execute:

winget install GitTower.GitFlowNext

5. Mudar para a branch de trabalho desejada

git switch <nomeDaBranch>
# ou
git checkout <nomeDaBranch>

6. Acessar a pasta da aplicação

cd my-app

7. Listar o conteúdo da pasta atual

ls

8. Abrir o VS Code a partir do Git Bash

code .

9. Encerrar o Git Bash

exit

10. Abrir o terminal no VS Code e instalar dependências

No VS Code, abra um novo terminal usando o Command Prompt (CMD) e instale as dependências:

npm install
# ou
npm i

Atenção: Certifique-se de que o terminal está dentro da pasta my-app.

11. Executar o projeto em modo de desenvolvimento

npm run dev

Antes de iniciar a codificação, certifique-se de que seu repositório local está sincronizado com a branch de referência.

1. Clonar e checar branches

git clone <endereco-remoto-repositorio>
cd my-app
git branch -a

2. Sincronizar com a branch do professor

Se você precisa iniciar exatamente do ponto oficial ou corrigir problemas locais:

# Baixar dados atualizados
git fetch origin

# Caso vá criar sua branch nova a partir do professor:
git switch -c feature/exemplo-rmSeuRM origin/feature/exemplo-pf0670

# OU caso precise resetar sua branch atual para o estado oficial:
git reset --hard origin/feature/exemplo-pf0670

3. Instalar dependências e rodar

npm install
npm run dev

id: fundamentos-react-hooks summary: Guia Definitivo: Componentes, Props, Hooks e Renderização Condicional categories: react, frontend tags: fiap, frontend status: Published authors: TDS Professor

Fundamentos do React: Componentes, Props e Hooks

Um componente funcional é uma função comum do JavaScript que tem apenas uma regra principal: ela precisa retornar um código visual (HTML/JSX).

Em vez de construir uma página inteira de uma vez, você cria pequenos pedaços isolados (como um botão, um cabeçalho ou um cartão) e junta todos eles depois.

Exemplo Prático

Aqui criamos um componente chamado CartaoCyberpunk. Ele é apenas uma função que retorna uma div estilizada.

export default function CartaoCyberpunk() {
  return (
    <div style={{ 
      backgroundColor: '#0d0d0d', 
      border: '2px solid #39ff14', 
      padding: '20px',
      color: '#39ff14' 
    }}>
      <h2>Acesso ao Sistema</h2>
      <p>Terminal ativado com sucesso.</p>
    </div>
  );
}

Como usar? Para colocar esse componente na sua tela principal, você o importa e o escreve como se fosse uma tag HTML normal: .

Props (abreviação de propriedades) são informações que você envia de fora para dentro de um componente.

Se você criar um componente de botão, não faz sentido escrever o texto dele fixo no código, senão todos os botões do seu site terão o mesmo texto. As props resolvem isso permitindo que você passe valores diferentes toda vez que usar o componente.

Exemplo Prático

Vamos modificar o cartão anterior para receber um titulo e uma mensagem via props.

// 1. Definimos o que o componente vai receber
interface CartaoProps {
  titulo: string;
  mensagem: string;
}

// 2. Recebemos as props usando a desestruturação { titulo, mensagem }
export default function CartaoDinamico({ titulo, mensagem }: CartaoProps) {
  return (
    <div style={{ border: '2px solid #ff00ff', padding: '20px', color: '#ff00ff' }}>
      <h2>{titulo}</h2>
      <p>{mensagem}</p>
    </div>
  );
}

Como usar? Ao chamar o componente na tela principal, você entrega as informações assim:

Hook (que significa "gancho") é uma função especial nativa do React.

Como os componentes funcionais são apenas funções simples de JavaScript, eles não têm memória e não sabem quando a tela muda. Os Hooks servem para "enganchar" recursos extras nessas funções simples, como dar a elas uma memória interna ou a capacidade de observar mudanças.

Regra de ouro: Todo Hook obrigatoriamente começa com a palavra use (exemplo: useState, useEffect).

O useState é a memória do componente. Ele guarda um valor que pode mudar com o tempo. A grande vantagem é: toda vez que o valor do

useState

muda, o React atualiza a tela automaticamente para mostrar o novo valor.

Exemplo Prático: Um contador

import { useState } from 'react';

export default function Contador() {
  // 1. Criamos a memória. 
  // 'numero' é o valor atual. 'setNumero' é a única função que pode alterar esse valor.
  // O (0) significa que o número começa em zero.
  const [numero, setNumero] = useState(0);

  function aumentar() {
    setNumero(numero + 1); // Avisa o React para mudar o valor e atualizar a tela
  }

  return (
    <div>
      <p>Tentativas de login: {numero}</p>
      <button onClick={aumentar}>Tentar Novamente</button>
    </div>
  );
}

O useEffect é um observador. Ele serve para executar um pedaço de código em momentos específicos, geralmente em duas situações:

  1. Assim que o componente aparece na tela pela primeira vez.
  2. Toda vez que uma variável específica muda de valor.

Exemplo Prático: Mudando o título da aba

import { useState, useEffect } from 'react';

export default function Monitor() {
  const [status, setStatus] = useState('Aguardando...');

  // O useEffect roda a função interna toda vez que a variável 'status' mudar.
  useEffect(() => {
    // Ação: Mudar o título da aba do navegador
    document.title = `Sistema: ${status}`;
  }, [status]); // O array [status] é a lista de dependências (o que ele está vigiando).

  return (
    <div>
      <p>Status atual: {status}</p>
      <button onClick={() => setStatus('Conectado')}>Conectar</button>
    </div>
  );
}

O useParams faz parte do pacote react-router. Ele serve para capturar valores dinâmicos que o usuário digitou no endereço do navegador (URL).

Se você tem uma rota configurada como /usuario/:id, o useParams captura o que foi digitado no lugar do :id.

Exemplo Prático

Se o usuário acessar o endereço http://seusite.com/usuario/993...

import { useParams } from 'react-router';

export default function PerfilUsuario() {
  // O hook extrai a parte móvel da URL e guarda na variável 'id'
  const { id } = useParams<{ id: string }>();

  return (
    <div>
      <h1>Perfil do Usuário</h1>
      <p>Você está acessando os dados do usuário número: {id}</p>
    </div>
  );
}

O useRef serve para selecionar e interagir com um elemento HTML físico na tela, de forma direta. É o equivalente moderno de usar o antigo document.getElementById().

Ele guarda a referência daquela tag HTML, permitindo que você aplique ações diretas, como dar foco em um campo de texto ou ler a largura de uma imagem.

Exemplo Prático: Dando foco automático no campo de texto

import { useRef } from 'react';

export default function Formulario() {
  // 1. Criamos a referência vazia
  const inputNome = useRef<HTMLInputElement>(null);

  function focarNoCampo() {
    // 3. Acessamos o elemento físico (.current) e aplicamos a ação de foco (.focus())
    inputNome.current?.focus();
  }

  return (
    <div>
      {/* 2. Conectamos a referência diretamente na tag HTML usando ref={} */}
      <input type="text" ref={inputNome} placeholder="Digite seu nome" />
      <button onClick={focarNoCampo}>Focar no Campo</button>
    </div>
  );
}

O useLocation também pertence ao react-router. Ele lê e retorna os dados do endereço atual exato em que o usuário está no momento. Diferente do useParams (que pega apenas uma variável específica), o useLocation pega o caminho inteiro.

Exemplo Prático

Se o usuário estiver no endereço http://seusite.com/configuracoes/rede...

import { useLocation } from 'react-router';

export default function RastreadorRota() {
  // Captura o objeto completo com os dados da URL atual
  const local = useLocation();

  return (
    <div>
      <p>O caminho completo que você está acessando é: {local.pathname}</p>
      {/* O resultado escrito na tela será: /configuracoes/rede */}
    </div>
  );
}

Nota técnica: A ação de redirecionar o usuário via código no React Router é feita pelo hook useNavigate.

O useNavigate serve para trocar a tela do usuário através de um comando no código, sem que ele precise clicar em um link padrão. É muito usado após o preenchimento de um formulário ou após um login bem-sucedido.

Exemplo Prático

import { useNavigate } from 'react-router';

export default function TelaLogin() {
  // 1. Inicializa o hook de navegação
  const navegar = useNavigate();

  function fazerLogin() {
    // Aqui aconteceria a verificação de senha...
    
    // 2. Se a senha estiver correta, redireciona o usuário para o painel principal
    navegar('/painel');
  }

  return (
    <div>
      <button onClick={fazerLogin}>Entrar no Sistema</button>
    </div>
  );
}

O operador ternário é um atalho para o if/else tradicional. No React, usamos o ternário dentro do HTML (JSX) para exibir uma informação ou outra dependendo de uma condição (renderização condicional).

A estrutura é dividida em três partes: Condição ? Exibe isso se for Verdade : Exibe isso se for Falso

Exemplo Prático: Controle de Acesso

import { useState } from 'react';

export default function PainelAcesso() {
  const [logado, setLogado] = useState(false);

  return (
    <div style={{ backgroundColor: '#1a1a1a', padding: '20px' }}>
      
      {/* Lógica Ternária sendo aplicada diretamente no visual */}
      {logado ? (
        <h2 style={{ color: '#39ff14' }}>Acesso Liberado: Bem-vindo!</h2>
      ) : (
        <h2 style={{ color: '#ff003c' }}>Acesso Negado: Faça Login.</h2>
      )}

      {/* Botão que inverte o valor de verdadeiro para falso e vice-versa */}
      <button onClick={() => setLogado(!logado)}>
        Trocar Status
      </button>
      
    </div>
  );
}

Nesta etapa, vamos transformar nossa aplicação em um sistema com múltiplas telas. Utilizaremos o react-router para ensinar o React a trocar de página sem precisar recarregar o navegador do zero.

1. Instalação do Pacote

Abra o terminal na pasta do seu projeto e execute o comando abaixo para instalar a biblioteca de roteamento:

npm i react-router

O que fizemos aqui? O comando i é a abreviação de install. A biblioteca react-router funciona como o "GPS" da nossa aplicação. É ela quem mapeia qual componente deve ser exibido na tela dependendo do endereço (URL) que o usuário digitar.

2. Criação da Estrutura de Pastas

Dentro da sua pasta src, crie uma nova pasta chamada routes. Dentro dela, crie as subpastas e os arquivos exatamente como no esquema abaixo:

src/
└── routes/
    ├── Home/index.tsx
    ├── Produtos/index.tsx
    ├── EditarProdutos/index.tsx
    └── Error/index.tsx

Por que estruturar assim?

Adicione uma função básica dentro de cada arquivo index.tsx criado, apenas para termos o que renderizar. Por exemplo, no Home/index.tsx:

export default function Home() {
  return <h1>Página Inicial</h1>;
}

3. Configurando o Roteador (main.tsx)

O arquivo main.tsx é o coração do projeto. Vamos configurá-lo para ser o gerente das nossas rotas. Substitua o conteúdo atual por este:

import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { createBrowserRouter, RouterProvider } from 'react-router';

// Importação das nossas páginas
import App from './App';
import Home from './routes/Home';
import Produtos from './routes/Produtos';
import EditarProdutos from './routes/EditarProdutos';
import Error from './routes/Error';

// 1. Criando o mapa de rotas
const router = createBrowserRouter([
  {
    path: "/",
    element: <App />,
    errorElement: <Error />,
    children: [
      { path: "/", element: <Home /> },
      { path: "/produtos", element: <Produtos /> },
      { path: "/editar-produtos", element: <EditarProdutos /> }
    ]
  }
]);

// 2. Injetando o roteador na aplicação
createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <RouterProvider router={router} />
  </StrictMode>
);

Dissecando o código:

4. O Ponto de Troca e a Navegação (App.tsx)

Agora precisamos preparar o nosso componente raiz (App.tsx) para receber e trocar as telas filhas.

import { Outlet, Link } from 'react-router';

export default function App() {
  return (
    <>
      <header>
        <nav>
          <Link to="/">Início</Link> | 
          <Link to="/produtos">Produtos</Link>
        </nav>
      </header>

      {/* Onde a mágica acontece */}
      <Outlet />

      <footer>
        <p>© Sistema de Produtos</p>
      </footer>
    </>
  );
}

2. Criar Mock de Dados (src/data/listaProdutos.ts)

Um dado "mockado" é um dado fictício. Como ainda não temos um banco de dados real ou uma API conectada à internet, vamos criar uma lista manual para simular o que o servidor nos devolveria.

Crie o arquivo e adicione a lista expandida abaixo:

import { TipoProduto } from '../types/types';

export const listaProdutos: TipoProduto[] = [
  {
    id: 1,
    nome: "Headset Gamer Sem Fio",
    preco: 299.90,
    descricao: "Áudio espacial 7.1 e microfone retrátil.",
    avatar: "https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=120&auto=format&fit=crop&q=80"
  },
  {
    id: 2,
    nome: "Teclado Mecânico RGB",
    preco: 249.00,
    descricao: "Switches mecânicos rápidos.",
    avatar: "https://images.unsplash.com/photo-1587829741301-dc798b83add3?w=120&auto=format&fit=crop&q=80"
  },
  {
    id: 3,
    nome: "Mouse Gamer Sem Fio",
    preco: 150.00,
    descricao: "Sensor óptico de alta precisão e bateria de longa duração.",
    avatar: "https://images.unsplash.com/photo-1527814050087-379381547969?w=120&auto=format&fit=crop&q=80"
  },
  {
    id: 4,
    nome: "Monitor Ultrawide 29\"",
    preco: 1200.00,
    descricao: "Tela IPS com taxa de atualização de 75Hz e HDR10.",
    avatar: "https://images.unsplash.com/photo-1527443224154-c4a3942d3acf?w=120&auto=format&fit=crop&q=80"
  },
  {
    id: 5,
    nome: "Cadeira Gamer Ergonômica",
    preco: 850.00,
    descricao: "Apoio lombar ajustável e inclinação de até 180° graus.",
    avatar: "https://images.unsplash.com/photo-1598550476439-6847785fcea6?w=120&auto=format&fit=crop&q=80"
  },
  {
    id: 6,
    nome: "Webcam Full HD 1080p",
    preco: 199.90,
    descricao: "Foco automático e microfone embutido com redutor de ruído.",
    avatar: "https://images.unsplash.com/photo-1621259182978-fbf93132d53d?w=120&auto=format&fit=crop&q=80"
  }
];

O que fizemos aqui?

3. Consumir Dados no Componente (src/routes/Produtos/index.tsx)

Agora vamos conectar a nossa lista de mentirinha com a tela do navegador. Abra o componente de Produtos e substitua pelo código abaixo:

import { useState, useEffect } from 'react';
import { Link } from 'react-router';
import { TipoProduto } from '../../types/types';
import { listaProdutos } from '../../data/listaProdutos';

export default function Produtos() {
  // 1. Criando a "gaveta de memória" do componente
  const [produtos, setProdutos] = useState<TipoProduto[]>([]);

  // 2. Disparando a busca de dados ao carregar a página
  useEffect(() => {
    setProdutos(listaProdutos);
  }, []);

  return (
    <main style={{ padding: '20px' }}>
      <h1>Painel de Produtos</h1>
      
      {/* 3. Estruturando a tabela */}
      <table border={1} cellPadding={10} style={{ width: '100%', borderCollapse: 'collapse' }}>
        
        {/* Cabeçalho das colunas */}
        <thead>
          <tr style={{ backgroundColor: '#2c3e50', color: '#ffffff' }}>
            <th>Foto</th>
            <th>ID</th>
            <th>Nome</th>
            <th>Preço</th>
            <th>Ações</th>
          </tr>
        </thead>
        
        {/* 4. Corpo da Tabela: Gerando as linhas dinamicamente */}
        <tbody>
          {produtos.map((item) => (
            <tr key={item.id}>
              <td>
                <img 
                  src={item.avatar} 
                  alt={item.nome} 
                  width={60} 
                  height={60} 
                  style={{ objectFit: 'cover' }} 
                />
              </td>
              <td>{item.id}</td>
              <td>{item.nome}</td>
              <td>R$ {item.preco.toFixed(2)}</td>
              <td>
                {/* 5. Link dinâmico passando o ID na URL */}
                <Link to={`/editar-produtos/${item.id}`}>Editar</Link>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </main>
  );
}

Dissecando o código passo a passo: