Fundamentos de React

JavaScript, JSX, listas, state e props (16 exercícios).

Por Fábio Linhares • Instituto Infnet

Ao encarar estes 16 exercícios, você vai atravessar o “miolo duro” do React: o ponto em que a interface deixa de ser um amontoado de tags e vira um sistema previsível, construído a partir de dados, regras e componentes.

Os desafios começam no básico que muita gente ignora: entender o que o JavaScript realmente está fazendo quando você declara variáveis (let/const), manipula valores primitivos (strings, números, booleanos) e lida com tipos referenciados (objetos e arrays). Aqui você vai treinar uma habilidade que separa o iniciante do competente: ler dados, transformar dados e apresentar dados sem se perder em “gambiarras” de DOM.

Em seguida, você vai encarar a parte que dá identidade ao React: pensar em UI como função do estado. Você vai montar páginas simples com JSX, mas também vai aprender a construir interfaces que mudam conforme condições (hora do dia, status do usuário) e que surgem de coleções (listas de tarefas, cards de produtos). Isso exige um salto mental: em vez de “mandar” a tela mudar, você descreve como ela deve ser para cada situação — e deixa o React fazer o trabalho mecânico.

Você também vai enfrentar uma das áreas onde bugs mais aparecem em aplicações reais: renderizar listas corretamente. Parece trivial até você perceber que “loop + key” é o tipo de detalhe que, se feito errado, cria problemas estranhos que parecem assombração (inputs trocando de lugar, itens reaparecendo, estado indo parar no componente errado). Resolver bem esses exercícios te dá uma competência prática de engenharia: evitar bugs que não são óbvios.

Outro desafio importante é aprender a transformar lógica em funções limpas (soma, conversão de temperatura, par/ímpar, diferença). Isso não é “só matemática”: é treinar pensamento funcional aplicado, onde você consegue isolar regras, testar mentalmente e reaproveitar código sem efeitos colaterais desnecessários. Quando isso se encaixa com React, seu código fica mais previsível e mais fácil de manter.

A reta final costura as peças mais valiosas para construir aplicações de verdade: componentes reutilizáveis, props como contrato (dados descem, ações sobem) e state para lidar com interação (contador). Se você concluir todos, você terá passado pelo essencial de “pensar em componentes” e de projetar a interface a partir de dados e responsabilidades, não a partir de improviso.

Se você conseguir resolver todas as questões com entendimento (não só copiando), você dominará, na prática:

• Fluência de JavaScript aplicada ao React: declarar, compor e usar variáveis, funções e expressões para gerar UI de forma limpa.
• Modelagem de dados simples e complexos (primitivos, objetos, arrays) e renderização segura.
• Condicionais e coleções com map e chaves estáveis, evitando bugs típicos.
• Modelo mental do React: “a tela é consequência do estado”, para prever comportamento antes de rodar.
• Componentes reutilizáveis e passagem de dados via props, organizando a UI em responsabilidades claras.
• Interações básicas com state, sem confundir “mudar variável” com “mudar a UI”.
• Depuração com calma: dados → render → tela, em vez de tratar React como magia.

Por fim, você não terá só um conjunto de respostas. Você terá uma base operacional para começar a construir interfaces React pequenas e médias com previsibilidade e, mais importante, com método.

A forma mais prática de fazer esses 16 exercícios é: criar um projeto React (com Vite) e colocar cada exercício como uma seção/componente dentro do App.jsx. Você estuda “um por vez” comentando/descomentando o que renderiza.
BLOCO 01
Exercícios 1–3 (setup, Flexbox/eixos e “Hello, React!”)
Objetivo: montar o laboratório com Vite e começar UI em React com evidência.
Preparação (uma vez só)
1) Crie o projeto com Vite.
2) Substitua src/App.jsx e src/App.css pelos códigos desta página.
npm create vite@latest fundamentos-react -- --template react
cd fundamentos-react
npm install
npm run dev
Exercício 1 — Flexbox (direção e eixos) + “O que é React”
Ideia-chave: flex-direction define o eixo principal. justify-content alinha no eixo principal; align-items no eixo transversal.
Validação: veja os blocos mudando de “lado a lado” (row) para “empilhado” (column) e perceba o que muda quando você altera justify-content vs align-items.
Erros comuns: achar que justify-content sempre é “horizontal”. O eixo depende de flex-direction.
Exercício 2 — Histórico do ReactJS (linha do tempo)
Você vai renderizar uma linha do tempo a partir de um array de eventos usando map e um <time> por item.
Validação: confira se cada item tem key estável e se a UI está vindo de dados.
Exercício 3 — “Hello, React!”
Ao abrir http://localhost:5173, você deve ver a saída do componente do exercício 3 quando ele for o único renderizado.
Se você quiser usar isso como “modo laboratório”, a rotina mais eficiente é: (1) abra um exercício, (2) mexa em uma variável/prop/estilo, (3) diga o que você espera ver, (4) valide no navegador.
BLOCO 02
Exercícios 4–6 (JS: let/const, primitivos, objeto/array)
Objetivo: manipular dados e renderizar com JSX sem “gambiarras de DOM”.
Exercício 4 — let e const
Regra prática: use const por padrão; use let apenas quando realmente vai reatribuir.
Em React, reatribuição para “estado” não é com let: é com useState (ex. 15).
Exercício 5 — valores primitivos (number/string/boolean)
Você pratica renderização de dados simples e condicional baseada em boolean.
Exercício 6 — tipos referenciados (objeto e array)
Você pratica: objeto para “entidade” e array para coleção, renderizando lista com map.
Consenso: ao atualizar objetos/arrays que vivem em state, faça updates imutáveis (cópia), porque mutação gera bugs sutis.
// exemplos de referência dentro do App.jsx
// Ex4: let/const, Ex5: primitivos, Ex6: objeto + array + map + key
BLOCO 03
Exercícios 7–9 (template strings, condicionais, listas com map/key)
Objetivo: transformar “dados do mundo” (hora, listas) em UI previsível.
Exercício 7 — Template Strings
Você pratica interpolação com crase: `texto ${variavel}`.
Também vê como “dados de ambiente” (hora) geram UI.
Exercício 8 — condicionais (bom dia/tarde/noite)
Você pratica regra de negócio simples: hora → saudação.
Repare: é o mesmo padrão mental de “UI = f(estado)”, só que aqui o “estado” vem do relógio.
Exercício 9 — loop para renderizar lista
Você pratica map e key estável.
Consenso: evite index como key quando a lista pode mudar de ordem/itens, porque pode “embaralhar” UI e estado interno.
// dica de verificação
// - liste com map
// - use key estável (string ou id)
// - force mudanças na lista e veja se a UI permanece coerente
BLOCO 04
Exercícios 10–11 (funções: soma e conversão)
Objetivo: treinar funções puras e renderizar resultados com clareza.
Exercício 10 — função (soma)
Função pura: dados A e B entram, resultado sai (sem efeitos colaterais).
Exercício 11 — função (Celsius → Fahrenheit)
Mesmo padrão: regra isolada + renderização do resultado.
Esse é o treino “invisível” que reduz bugs: você consegue simular mentalmente entradas e saídas antes de rodar.
BLOCO 05
Exercícios 12–13 (arrow functions: diferença e par/ímpar)
Objetivo: aplicar sintaxe curta e condicional com boolean.
Exercício 12 — arrow function (diferença)
Treine expressão direta e retorno implícito (quando fizer sentido).
Exercício 13 — arrow function (par/ímpar)
Você pratica: função que retorna boolean + condicional para mostrar o texto final.
BLOCO 06
Exercícios 14–16 (componentes, state e props) + códigos
Objetivo: fechar o ciclo: UI por dados, composição por componentes e interação por state.
Exercício 14 — cards dinâmicos (array de objetos)
Você pratica componente reutilizável (<Card />) + map em array de objetos.
Ponte natural para props: dados entram, componente apresenta.
Exercício 15 — state (contador)
Você pratica useState e atualização baseada no valor anterior: setCount(c => c + 1).
Esse padrão evita bugs de “valor antigo” em atualizações sequenciais.
Exercício 16 — props (pai → filho)
Contrato de dados: o pai “dono da informação” passa props; o filho só apresenta.
Quando você sentir “React está confuso”, volte para a sequência: dados → render → tela. Quase sempre o bug está em dados errados, key errada, ou expectativa errada sobre state.
Código — src/App.jsx
Substitua todo o arquivo por este conteúdo.
import "./App.css";
import { useState } from "react";

function saudacaoPorHora(h) {
  if (h >= 5 && h < 12) return "Bom dia";
  if (h >= 12 && h < 18) return "Boa tarde";
  return "Boa noite";
}

function Ex1_FlexboxEixos() {
  return (
    <div className="stack">
      <h3>O que é React</h3>
      <p>
        React é uma biblioteca para construir interfaces a partir de componentes.
        Você descreve a UI como uma função do estado e o React recalcula a tela
        quando o estado muda.
      </p>

      <div className="grid2">
        <div className="panel">
          <h4>Flex: row (eixo principal horizontal)</h4>
          <div className="flexDemo row">
            <div className="box">A</div>
            <div className="box">B</div>
            <div className="axisHint">
              <div><b>main axis</b> →</div>
              <div><b>cross axis</b> ↓</div>
            </div>
          </div>
          <p className="note">
            Aqui, <code>justify-content</code> mexe no horizontal (main) e{" "}
            <code>align-items</code> no vertical (cross).
          </p>
        </div>

        <div className="panel">
          <h4>Flex: column (eixo principal vertical)</h4>
          <div className="flexDemo column">
            <div className="box">A</div>
            <div className="box">B</div>
            <div className="axisHint">
              <div><b>main axis</b> ↓</div>
              <div><b>cross axis</b> →</div>
            </div>
          </div>
          <p className="note">
            Aqui, o eixo principal virou vertical. Agora{" "}
            <code>justify-content</code> mexe no vertical (main).
          </p>
        </div>
      </div>
    </div>
  );
}

function Ex2_HistoricoReact() {
  const eventos = [
    { ano: "2011", texto: "Uso interno (News Feed) e evolução inicial" },
    { ano: "2012", texto: "Adoção em aplicações do ecossistema Instagram" },
    { ano: "2013", texto: "Open-source (JSConf US)" },
    { ano: "2015", texto: "React Native: anúncio e abertura do projeto" },
    {
      ano: "2017",
      texto: "React 16: grande atualização (base para evoluções internas)",
    },
    { ano: "2019", texto: "Hooks estáveis no React 16.8" },
    { ano: "2024", texto: "React 19: novas capacidades e melhorias" },
  ];

  return (
    <div className="stack">
      <h3>Histórico do ReactJs</h3>
      <ol className="timeline">
        {eventos.map((e) => (
          <li key={e.ano} className="timelineItem">
            <time className="timelineYear">{e.ano}</time>
            <span>{e.texto}</span>
          </li>
        ))}
      </ol>
      <p className="note">
        A lista foi renderizada com <code>map</code>, e cada item tem{" "}
        <code>key</code> estável.
      </p>
    </div>
  );
}

function Ex3_HelloReact() {
  return (
    <div className="stack">
      <h3>Hello, React!</h3>
      <p className="note">
        Se você renderizar somente este componente no App, você tem exatamente a
        “tela inicial” do exercício 3.
      </p>
    </div>
  );
}

function Ex4_LetConst() {
  let nome = "Ana";
  const idade = 23;

  nome = nome.toUpperCase();

  return (
    <div className="stack">
      <h3>let e const</h3>
      <p>
        Nome: <b>{nome}</b>
      </p>
      <p>
        Idade: <b>{idade}</b>
      </p>
      <p className="note">
        Em React, para “mudar valores na tela”, normalmente você usa{" "}
        <code>useState</code> (exercício 15), não reatribuição com{" "}
        <code>let</code>.
      </p>
    </div>
  );
}

function Ex5_Primitivos() {
  const nome = "João";
  const idade = 30;
  const assinante = true;

  return (
    <div className="stack">
      <h3>Perfil com valores primitivos</h3>
      <p>
        Nome: <b>{nome}</b>
      </p>
      <p>
        Idade: <b>{idade}</b>
      </p>
      <p>
        Status:{" "}
        {assinante ? (
          <span className="tag ok">Assinante</span>
        ) : (
          <span className="tag">Gratuito</span>
        )}
      </p>
    </div>
  );
}

function Ex6_ObjetoArray() {
  const livro = { titulo: "Estruturas de Dados", autor: "A. Pessoa", ano: 2022 };
  const capitulos = ["Listas", "Pilhas", "Filas", "Árvores", "Grafos"];

  return (
    <div className="stack">
      <h3>Objeto (livro) + Array (capítulos)</h3>
      <p>
        <b>{livro.titulo}</b> — {livro.autor} ({livro.ano})
      </p>

      <ul>
        {capitulos.map((c) => (
          <li key={c}>{c}</li>
        ))}
      </ul>

      <p className="note">
        Reparou na <code>key</code>? Aqui o capítulo (string) é estável,
        então funciona bem.
      </p>
    </div>
  );
}

function Ex7_TemplateStrings() {
  const nome = "Marina";
  const agora = new Date();
  const hora = agora.getHours();
  const msg = `Bem-vindo(a), ${nome}! Agora são ${hora}h. ${saudacaoPorHora(hora)}!`;

  return (
    <div className="stack">
      <h3>Template Strings</h3>
      <p>{msg}</p>
      <p className="note">
        Template string usa crase: <code>{'`texto ${variavel}`'}</code>.
      </p>
    </div>
  );
}

function Ex8_CondicionalHora() {
  const hora = new Date().getHours();
  const saudacao = saudacaoPorHora(hora);

  return (
    <div className="stack">
      <h3>Condicional por hora</h3>
      <p>
        Agora são <b>{hora}h</b> → <b>{saudacao}</b>
      </p>
    </div>
  );
}

function Ex9_ListaTarefas() {
  const tarefas = ["Estudar JSX", "Praticar props", "Treinar map + key", "Revisar useState"];

  return (
    <div className="stack">
      <h3>Loop para renderizar lista</h3>
      <ul>
        {tarefas.map((t) => (
          <li key={t}>{t}</li>
        ))}
      </ul>
      <p className="note">
        Evite <code>index</code> como <code>key</code> quando a lista pode mudar:
        isso causa bugs “fantasmas”.
      </p>
    </div>
  );
}

function Ex10_FuncaoSoma() {
  function soma(a, b) {
    return a + b;
  }
  const a = 7;
  const b = 5;

  return (
    <div className="stack">
      <h3>Função: soma</h3>
      <p>
        {a} + {b} = <b>{soma(a, b)}</b>
      </p>
    </div>
  );
}

function Ex11_CelsiusFahrenheit() {
  function cParaF(c) {
    return (c * 9) / 5 + 32;
  }
  const c = 25;

  return (
    <div className="stack">
      <h3>Função: Celsius → Fahrenheit</h3>
      <p>
        {c}°C = <b>{cParaF(c)}°F</b>
      </p>
    </div>
  );
}

function Ex12_ArrowDiferenca() {
  const diferenca = (a, b) => a - b;
  const a = 10;
  const b = 4;

  return (
    <div className="stack">
      <h3>Arrow Function: diferença</h3>
      <p>
        {a} - {b} = <b>{diferenca(a, b)}</b>
      </p>
    </div>
  );
}

function Ex13_ArrowParImpar() {
  const ehPar = (n) => n % 2 === 0;
  const n = 7;

  return (
    <div className="stack">
      <h3>Arrow Function: par ou ímpar</h3>
      <p>
        {n} é <b>{ehPar(n) ? "par" : "ímpar"}</b>
      </p>
    </div>
  );
}

function Card({ titulo, preco, estoque }) {
  return (
    <div className="card">
      <h4 className="cardTitle">{titulo}</h4>
      <p className="cardPrice">R$ {preco.toFixed(2)}</p>
      <p className="note">
        {estoque > 0 ? (
          <span className="tag ok">Em estoque</span>
        ) : (
          <span className="tag">Indisponível</span>
        )}
      </p>
    </div>
  );
}

function Ex14_CardsDinamicos() {
  const produtos = [
    { id: "p1", titulo: "Teclado", preco: 129.9, estoque: 12 },
    { id: "p2", titulo: "Mouse", preco: 79.9, estoque: 0 },
    { id: "p3", titulo: "Monitor", preco: 899.0, estoque: 5 },
  ];

  return (
    <div className="stack">
      <h3>Cards dinâmicos (map + componente)</h3>
      <div className="cardsGrid">
        {produtos.map((p) => (
          <Card key={p.id} titulo={p.titulo} preco={p.preco} estoque={p.estoque} />
        ))}
      </div>
      <p className="note">
        Repare: <code>key</code> estável (id), e dados indo por <code>props</code>.
      </p>
    </div>
  );
}

function Ex15_ContadorState() {
  const [count, setCount] = useState(0);

  return (
    <div className="stack">
      <h3>State: contador</h3>
      <div className="counter">
        <button onClick={() => setCount((c) => c - 1)}>-</button>
        <span className="counterValue">{count}</span>
        <button onClick={() => setCount((c) => c + 1)}>+</button>
      </div>
      <p className="note">
        Use <code>setCount(c =&gt; c + 1)</code> quando o próximo valor depende do anterior.
      </p>
    </div>
  );
}

function Filho({ nome, area }) {
  return (
    <div className="panel">
      <p>
        Nome recebido via props: <b>{nome}</b>
      </p>
      <p>
        Área recebida via props: <b>{area}</b>
      </p>
    </div>
  );
}

function Ex16_PropsPaiFilho() {
  const nome = "Carlos";
  const area = "Frontend (React)";

  return (
    <div className="stack">
      <h3>Props: pai → filho</h3>
      <p className="note">
        O pai define os dados e passa para o filho. O filho não “adivinha” nada: só apresenta.
      </p>
      <Filho nome={nome} area={area} />
    </div>
  );
}

function Secao({ id, titulo, children }) {
  return (
    <section id={id} className="section">
      <h2 className="sectionTitle">{titulo}</h2>
      {children}
    </section>
  );
}

export default function App() {
  const links = [
    { id: "ex1", label: "Ex1" },
    { id: "ex2", label: "Ex2" },
    { id: "ex3", label: "Ex3" },
    { id: "ex4", label: "Ex4" },
    { id: "ex5", label: "Ex5" },
    { id: "ex6", label: "Ex6" },
    { id: "ex7", label: "Ex7" },
    { id: "ex8", label: "Ex8" },
    { id: "ex9", label: "Ex9" },
    { id: "ex10", label: "Ex10" },
    { id: "ex11", label: "Ex11" },
    { id: "ex12", label: "Ex12" },
    { id: "ex13", label: "Ex13" },
    { id: "ex14", label: "Ex14" },
    { id: "ex15", label: "Ex15" },
    { id: "ex16", label: "Ex16" },
  ];

  return (
    <div className="page">
      <header className="header">
        <h1>Fundamentos de React — 16 exercícios</h1>
        <nav className="nav">
          {links.map((l) => (
            <a key={l.id} href={`#${l.id}`} className="navLink">
              {l.label}
            </a>
          ))}
        </nav>
      </header>

      <main className="main">
        <Secao id="ex1" titulo="Exercício 1 — Flexbox (direção/eixos) + O que é React">
          <Ex1_FlexboxEixos />
        </Secao>

        <Secao id="ex2" titulo="Exercício 2 — Histórico do ReactJs (linha do tempo)">
          <Ex2_HistoricoReact />
        </Secao>

        <Secao id="ex3" titulo='Exercício 3 — "Hello, React!"'>
          <Ex3_HelloReact />
        </Secao>

        <Secao id="ex4" titulo="Exercício 4 — let e const">
          <Ex4_LetConst />
        </Secao>

        <Secao id="ex5" titulo="Exercício 5 — Valores primitivos">
          <Ex5_Primitivos />
        </Secao>

        <Secao id="ex6" titulo="Exercício 6 — Objeto e array">
          <Ex6_ObjetoArray />
        </Secao>

        <Secao id="ex7" titulo="Exercício 7 — Template Strings">
          <Ex7_TemplateStrings />
        </Secao>

        <Secao id="ex8" titulo="Exercício 8 — Condicionais por hora">
          <Ex8_CondicionalHora />
        </Secao>

        <Secao id="ex9" titulo="Exercício 9 — Loop para lista de tarefas">
          <Ex9_ListaTarefas />
        </Secao>

        <Secao id="ex10" titulo="Exercício 10 — Função soma">
          <Ex10_FuncaoSoma />
        </Secao>

        <Secao id="ex11" titulo="Exercício 11 — Função Celsius → Fahrenheit">
          <Ex11_CelsiusFahrenheit />
        </Secao>

        <Secao id="ex12" titulo="Exercício 12 — Arrow Function diferença">
          <Ex12_ArrowDiferenca />
        </Secao>

        <Secao id="ex13" titulo="Exercício 13 — Arrow Function par/ímpar">
          <Ex13_ArrowParImpar />
        </Secao>

        <Secao id="ex14" titulo="Exercício 14 — Cards dinâmicos">
          <Ex14_CardsDinamicos />
        </Secao>

        <Secao id="ex15" titulo="Exercício 15 — State (contador)">
          <Ex15_ContadorState />
        </Secao>

        <Secao id="ex16" titulo="Exercício 16 — Props (pai → filho)">
          <Ex16_PropsPaiFilho />
        </Secao>
      </main>
    </div>
  );
}
Código — src/App.css
Substitua todo o arquivo por este conteúdo.
:root {
  font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
  color: #111;
  background: #fafafa;
}

* { box-sizing: border-box; }

.page { max-width: 1100px; margin: 0 auto; padding: 24px; }
.header { position: sticky; top: 0; background: #fafafa; padding-bottom: 12px; z-index: 10; }
.header h1 { margin: 0 0 10px 0; font-size: 20px; }

.nav {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}

.navLink {
  text-decoration: none;
  color: #0b57d0;
  background: #e8f0fe;
  padding: 6px 10px;
  border-radius: 999px;
  font-size: 12px;
}

.main { margin-top: 16px; display: grid; gap: 18px; }

.section {
  background: #fff;
  border: 1px solid #e8e8e8;
  border-radius: 12px;
  padding: 16px;
}

.sectionTitle { margin: 0 0 12px 0; font-size: 16px; }

.stack { display: grid; gap: 10px; }
.note { margin: 0; color: #555; font-size: 13px; }
code { background: #f2f2f2; padding: 2px 6px; border-radius: 6px; }

.grid2 { display: grid; gap: 12px; grid-template-columns: 1fr; }
@media (min-width: 900px) {
  .grid2 { grid-template-columns: 1fr 1fr; }
}

.panel {
  border: 1px dashed #d8d8d8;
  border-radius: 12px;
  padding: 12px;
  background: #fcfcfc;
}

.flexDemo {
  display: flex;
  gap: 10px;
  padding: 10px;
  border-radius: 12px;
  border: 1px solid #eee;
  background: #fff;
  justify-content: flex-start;
  align-items: center;
  min-height: 110px;
}

.flexDemo.row { flex-direction: row; }
.flexDemo.column { flex-direction: column; }

.box {
  width: 52px;
  height: 52px;
  display: grid;
  place-items: center;
  border-radius: 10px;
  border: 1px solid #ddd;
  background: #f6f6f6;
  font-weight: 700;
}

.axisHint {
  margin-left: auto;
  font-size: 12px;
  color: #444;
  padding: 6px 10px;
  border-radius: 10px;
  background: #f7f7ff;
  border: 1px solid #ececff;
}

.timeline { margin: 0; padding-left: 18px; display: grid; gap: 8px; }
.timelineItem { display: grid; grid-template-columns: 72px 1fr; gap: 10px; align-items: baseline; }
.timelineYear { font-weight: 700; color: #333; }

.tag {
  display: inline-block;
  padding: 3px 8px;
  border-radius: 999px;
  background: #eee;
  font-size: 12px;
}
.tag.ok { background: #e6f4ea; color: #137333; }

.cardsGrid {
  display: grid;
  gap: 12px;
  grid-template-columns: 1fr;
}
@media (min-width: 700px) {
  .cardsGrid { grid-template-columns: repeat(3, 1fr); }
}
.card {
  border: 1px solid #eee;
  border-radius: 14px;
  padding: 12px;
  background: #fff;
}
.cardTitle { margin: 0 0 6px 0; }
.cardPrice { margin: 0 0 10px 0; font-weight: 700; }

.counter {
  display: flex;
  align-items: center;
  gap: 12px;
}
.counter button {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  border: 1px solid #ddd;
  background: #fff;
  cursor: pointer;
  font-size: 18px;
}
.counterValue { font-size: 20px; font-weight: 800; min-width: 40px; text-align: center; }

Referência: Wikipedia — React (software): https://en.wikipedia.org/wiki/React_(software)