O que vamos construir
Um livro de visitas: um formulário em React envia uma mensagem ao teu servidor, o servidor guarda-a e mostra-a a cada visitante futuro. Lembras-te do formulário do Nível 2 que não tinha para onde enviar? Hoje pagamos essa dívida.
Vou mostrar-te: o backend do livro de visitas
Na pasta my-server, instala primeiro mais um pacote:
npm install cors
E edita server.js:
const express = require("express");
const cors = require("cors");
const app = express();
app.use(cors()); // allow the frontend on a different port to ask questions
app.use(express.json()); // understand JSON in incoming requests
const messages = [
{ name: "Martin", text: "First message! Long live the guestbook. 📖" },
];
// GET – hand out messages
app.get("/api/messages", (request, response) => {
response.json(messages);
});
// POST – accept a new message
app.post("/api/messages", (request, response) => {
const { name, text } = request.body;
// Never trust input: check it on the server too!
if (!name || !text || name.length > 50 || text.length > 500) {
return response.status(400).json({ error: "Invalid message." });
}
messages.push({ name, text });
response.json({ saved: true });
});
app.listen(3900, () => {
console.log("Server running at http://localhost:3900");
});
Coisas novas:
cors()– o frontend corre na porta 3901, o servidor na 3900. Os browsers normalmente bloqueiam pedidos «cross-origin» assim (regra de segurança chamada CORS); isto é como permites no servidor.app.post(...)– o teu primeiro endpoint POST! Os dados do formulário aparecem emrequest.body.- Verificar no servidor – o frontend já verifica o formulário, mas um atacante pode contornar o formulário e enviar um pedido direto. Por isso a regra de ferro: o backend verifica sempre e nunca confia no frontend.
status(400)significa «pedido inválido.»
Vou mostrar-te: o frontend do livro de visitas
No teu projeto React, cria src/GuestBook.jsx:
import { useState, useEffect } from 'react';
function GuestBook() {
const [messages, setMessages] = useState([]);
const [name, setName] = useState("");
const [text, setText] = useState("");
// On first render: download the messages from the server
useEffect(() => {
fetch("http://localhost:3900/api/messages")
.then((response) => response.json())
.then((data) => setMessages(data));
}, []);
function submit(event) {
event.preventDefault();
fetch("http://localhost:3900/api/messages", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name, text }),
})
.then((response) => response.json())
.then(() => {
setMessages([...messages, { name, text }]); // add it to the screen too
setName("");
setText("");
});
}
return (
<div>
<h2>Guestbook 📖</h2>
{messages.map((message, index) => (
<div className="card" key={index}>
<strong>{message.name}</strong>
<p>{message.text}</p>
</div>
))}
<form onSubmit={submit}>
<input
value={name}
onChange={(event) => setName(event.target.value)}
placeholder="Your name"
/>
<textarea
value={text}
onChange={(event) => setText(event.target.value)}
placeholder="Write a message..."
/>
<button type="submit">Send</button>
</form>
</div>
);
}
export default GuestBook;
Três últimas coisas novas no React:
useEffect(() => {...}, [])– «corre isto uma vez, quando o componente aparece pela primeira vez.» O sítio ideal para descarregar dados.fetchcommethod: "POST"– estamos a enviar dados;JSON.stringifyempacota em JSON.- Formulários ligados – o campo lê o valor do estado (
value={name}) e escreve de volta enquanto escreves (onChange). O formulário e o estado ficam sempre sincronizados.
Agora és tu 💪
- Põe os dois a correr: o servidor num terminal (
node server.js), React noutro (npm run dev -- --port 3901). Dois terminais, dois programas – bem-vindo ao full-stack! - Adiciona
<GuestBook />à tua app e experimenta: escreve uma mensagem, recarrega a página – a mensagem ainda está lá (enquanto o servidor estiver a correr). - Adapta o livro de visitas ao teu projeto: 🏫 mensagens para a escola · 🙋 mural para amigos · 🌍 dicas «para onde devemos ir?» de visitantes · ⚽ cânticos dos adeptos.
- Tenta enviar uma mensagem vazia – o frontend deixa passar (não tem verificação), mas o servidor rejeita. Depois adiciona verificação no frontend também, para o formulário ser educado como no Nível 2.
As mensagens desaparecem quando o servidor reinicia – só vivem num array na memória. Aplicações reais guardam-nas numa base de dados, que sobrevive a tudo. É a primeira coisa a aprender depois deste nível – palavras-chave: SQLite, PostgreSQL.
Verifica tu: Uma mensagem do formulário viaja para o servidor, é guardada e volta depois de recarregar a página. Acabaste de construir uma aplicação full-stack – frontend, backend, API. É exatamente o que programadores profissionais fazem todos os dias.
O que ficas a saber desta lição
useEffect(..., [])descarrega dados no primeiro render;fetchcom POST envia-os.- A regra de ferro da segurança: o servidor verifica cada entrada, mesmo quando o frontend também verifica.
- Full-stack = dois programas a correr (3901 + 3900) a conversar através de uma API.
© 2026 Ing. Martin Polak / AlgoRhino · Condições de uso do conteúdo