From cd89e05e5c299157f6a08a0e701c5c92a4bda61e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Ribal=20del=20R=C3=ADo?= Date: Fri, 13 Mar 2026 09:55:02 +0100 Subject: [PATCH 1/3] feat: class 11 --- pages/Bloque4/Server.py | 123 +++++ pages/Bloque4/protocolos.qmd | 581 ++++++++++++++++++++++++ pages/Bloque4/tester_http_ws_basic.html | 444 ++++++++++++++++++ 3 files changed, 1148 insertions(+) create mode 100644 pages/Bloque4/Server.py create mode 100644 pages/Bloque4/protocolos.qmd create mode 100644 pages/Bloque4/tester_http_ws_basic.html diff --git a/pages/Bloque4/Server.py b/pages/Bloque4/Server.py new file mode 100644 index 0000000..fdd1099 --- /dev/null +++ b/pages/Bloque4/Server.py @@ -0,0 +1,123 @@ +import asyncio +import json +import random +import threading +from http.server import BaseHTTPRequestHandler, HTTPServer +from datetime import datetime + +import websockets + + +# ========================================================= +# HTTP SERVER — PORT 3001 +# ========================================================= + +class TestHandler(BaseHTTPRequestHandler): + + # ----------- CORS HEADERS ----------- + + def _set_cors_headers(self): + self.send_header("Access-Control-Allow-Origin", "*") + self.send_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS") + self.send_header("Access-Control-Allow-Headers", "Content-Type") + + # ----------- OPTIONS (PRE-FLIGHT) ----------- + + def do_OPTIONS(self): + self.send_response(200) + self._set_cors_headers() + self.end_headers() + + # ----------- COMMON HANDLER ----------- + + def _handle_request(self): + content_length = int(self.headers.get('Content-Length', 0)) + body = self.rfile.read(content_length) if content_length > 0 else b'' + + print("\n==============================") + print("HTTP REQUEST RECEIVED") + print("Method:", self.command) + print("Path:", self.path) + print("Headers:", dict(self.headers)) + print("Body:", body.decode(errors="ignore")) + print("==============================\n") + + self.send_response(200) + self._set_cors_headers() + self.send_header("Content-Type", "text/plain") + self.end_headers() + + self.wfile.write(b"OK") + + def do_GET(self): + self._handle_request() + + def do_POST(self): + self._handle_request() + + def log_message(self, format, *args): + return + + +def run_http_server(): + server = HTTPServer(("0.0.0.0", 3001), TestHandler) + print("HTTP server listening on port 3001") + server.serve_forever() + + +# ========================================================= +# WEBSOCKET SERVER — PORT 3002 +# ========================================================= + +async def ws_handler(websocket): + print("WebSocket client connected") + + data_buffer = [] + + try: + while True: + value = random.uniform(0, 100) + + data_buffer.append({ + "time": datetime.now().strftime("%H:%M:%S"), + "value": value + }) + + data_buffer = data_buffer[-20:] + + await websocket.send(json.dumps(data_buffer)) + await asyncio.sleep(1) + + except websockets.exceptions.ConnectionClosedOK: + print("Client disconnected normally") + + except websockets.exceptions.ConnectionClosedError: + print("Client disconnected with error") + + +async def run_ws_server(): + print("WebSocket server listening on port 3002") + + async with websockets.serve( + ws_handler, + "0.0.0.0", + 3002 + ): + await asyncio.Future() + + +# ========================================================= +# MAIN +# ========================================================= + +if __name__ == "__main__": + + print("\n=== TEST SERVER STARTING ===") + + http_thread = threading.Thread( + target=run_http_server, + daemon=True + ) + http_thread.start() + + asyncio.run(run_ws_server()) \ No newline at end of file diff --git a/pages/Bloque4/protocolos.qmd b/pages/Bloque4/protocolos.qmd new file mode 100644 index 0000000..f9ed2f4 --- /dev/null +++ b/pages/Bloque4/protocolos.qmd @@ -0,0 +1,581 @@ +--- +title: "Protocolos de Comunicación" +subtitle: "HTTP, WebSockets, Hooks personalizados y Recharts" +author: "Javier Ribal del Río" +date: "2026-03-13" +date-modified: today +affiliation: "Hyperloop UPV" + +format: + html: default + revealjs: + history: false + chalkboard: true + output-file: Protocolos.html + parallax-background-image: ../../img/fondo.png + parallax-background-size: "cover" + pdf: default +format-links: + - pdf + - format: revealjs + text: Presentación + icon: file-slides +--- + +**Contenido** + +- HTTP básico para desarrollo web +- Métodos GET, POST, PUT, DELETE, HEAD +- WebSockets +- Hook personalizado para conexión en tiempo real +- Gráficas con Recharts + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +## HTTP +### ¿Qué es HTTP? + +HTTP (*HyperText Transfer Protocol*) es el protocolo fundamental de la web. + +Define cómo: + +- El cliente (navegador o app) +- Solicita recursos +- A un servidor + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +Modelo conceptual: + +``` +Cliente → Solicitud HTTP → Servidor +Cliente ← Respuesta HTTP ← Servidor +``` + +HTTP es **sin estado (stateless)**. + +Cada petición es independiente. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Componentes de una petición + +Una petición HTTP contiene: + +- Método +- URL +- Cabeceras (*headers*) +- Cuerpo (*body*, opcional) + +Ejemplo conceptual: + +``` +GET /users HTTP/1.1 +Host: api.example.com +Authorization: Bearer token +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Métodos HTTP principales + +#### GET + +- Solicita datos +- No modifica el servidor +- Debe ser idempotente + +Ejemplo: + +``` +GET /users +``` + + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +Uso típico en React: + +```jsx +fetch("/api/users") +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### POST + +- Envía datos al servidor +- Crea recursos nuevos +- Tiene cuerpo + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +Ejemplo: + +```jsx +fetch("/api/users", { + method: "POST", + body: JSON.stringify({ name: "Ana" }), + headers: { "Content-Type": "application/json" } +}); +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### PUT + +- Actualiza completamente un recurso existente +- Idempotente + +``` +PUT /users/3 +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### DELETE + +- Elimina un recurso + +``` +DELETE /users/3 +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### HEAD + +- Igual que GET +- No devuelve cuerpo +- Solo cabeceras + +Se utiliza para: + +- Comprobar existencia +- Tamaño +- Metadatos + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +## HTTP vs Comunicación en tiempo real + +HTTP funciona bajo el modelo: + +> Petición → Respuesta → Fin + +Si queremos datos continuamente: + +- Debemos repetir peticiones +- Introduce latencia +- Ineficiente + +Solución: **WebSockets** + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +## WebSockets + +WebSockets permiten comunicación bidireccional persistente. + +Características: + +- Conexión permanente +- Cliente y servidor pueden enviar datos +- Baja latencia +- Ideal para tiempo real + + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +Ejemplos: + +- Chats +- Juegos online +- Telemetría +- Trading +- Sistemas IoT + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Flujo conceptual + +``` +Cliente ↔ Servidor + conexión abierta +``` + +No se crea una nueva conexión por mensaje. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Creación de un WebSocket en JavaScript + +```jsx +const socket = new WebSocket("ws://localhost:8080"); +``` + +Eventos principales: + +- `onopen` +- `onmessage` +- `onclose` +- `onerror` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Recepción de mensajes + +```js +socket.onmessage = (event) => { + console.log("Mensaje:", event.data); +}; +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Envío de mensajes + +```js +socket.send("Hola servidor"); +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: +## Hook Personalizado + +Si usamos WebSockets directamente dentro del componente: + +- Mezclamos lógica de conexión con renderizado +- Código difícil de reutilizar +- Problemas de ciclo de vida + +Solución: **Hook personalizado** + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Hook personalizado + +Un hook personalizado es: + +> Una función que utiliza hooks internos para encapsular lógica reutilizable + +Convención: + +``` +useNombre() +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Hook `useWebSocket` + +```jsx +import { useEffect, useState } from "react"; + +export function useWebSocket(url) { + + const [data, setData] = useState(null); + + useEffect(() => { + + const socket = new WebSocket(url); + + socket.onmessage = (event) => { + setData(event.data); + }; + + return () => socket.close(); + + }, [url]); + + return data; +} +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Análisis conceptual + +- Se crea la conexión al montar +- Se actualiza el estado al recibir datos +- Se cierra al desmontar +- El componente solo consume datos + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Uso del hook + +```jsx +function Monitor() { + + const data = useWebSocket("ws://localhost:8080"); + + return ( +
+

Datos en tiempo real

+

{data}

+
+ ); +} +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +Flujo: + +1. Componente se renderiza +2. Hook abre conexión +3. Llegan datos +4. Estado cambia +5. Nuevo render + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +## Visualización de datos + +En aplicaciones reales no basta con mostrar texto. + +Necesitamos: + +- Gráficas +- Paneles de control +- Visualización clara + +Una librería popular para React es **Recharts**. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +## Recharts + +Recharts es una librería basada en: + +- Componentes React +- SVG +- Composición declarativa + +Instalación: + +```bash +npm install recharts +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Ejemplo básico + +```jsx +import { + LineChart, Line, XAxis, YAxis, + CartesianGrid, Tooltip +} from "recharts"; + +const data = [ + { t: 1, v: 10 }, + { t: 2, v: 15 }, + { t: 3, v: 8 } +]; + +function Grafica() { + return ( + + + + + + + + ); +} +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Interpretación + +Cada objeto representa un punto. + +``` +{ t: 1, v: 10 } +``` + +- `t` → eje X +- `v` → eje Y + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +## Integración completa + +WebSocket + Hook + Recharts + +Objetivo: + +> Visualizar datos en tiempo real + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Ejemplo conceptual + +```jsx +function Dashboard() { + + const data = useWebSocket("ws://localhost:8080"); + + const chartData = data + ? JSON.parse(data) + : []; + + return ( + + + + + + + ); +} +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Flujo completo de una app moderna + +``` +Servidor → WebSocket → Hook → Estado → React → Gráfica +``` + +Arquitectura típica de sistemas en tiempo real. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +## Material + +Servidor de testing de _Python_: [Enlace](Server.py). + +Instalar `websockets` con `pip install websockets` + +Tester de prueba: [Enlace](tester_http_ws_basic.html) (click derecho guardar enlace como) + +[https://recharts.github.io/](https://recharts.github.io/) \ No newline at end of file diff --git a/pages/Bloque4/tester_http_ws_basic.html b/pages/Bloque4/tester_http_ws_basic.html new file mode 100644 index 0000000..5343719 --- /dev/null +++ b/pages/Bloque4/tester_http_ws_basic.html @@ -0,0 +1,444 @@ + + + + + + Tester HTTP + WebSocket + + + +
+

Tester HTTP + WebSocket

+

Página básica en HTML y JavaScript para probar tu servidor HTTP en el puerto 3001 y el WebSocket en el puerto 3002.

+ +
+
+

HTTP

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+

El body solo se enviará en POST. El servidor debería mostrar por consola el método, la ruta, los headers y el body.

+
+ +
+

Respuesta HTTP

+ Sin petición +
Aquí aparecerá la respuesta del servidor.
+
+ +
+

WebSocket

+
+ + +
+
+ + + +
+
+ Desconectado +
+

Se espera recibir un JSON con este formato: [{"time":"12:00:00","value":10}, ...]

+
+ +
+

Mensajes WebSocket

+
Aquí aparecerán los mensajes recibidos por WebSocket.
+
+ +
+

Gráfica en tiempo real

+ +

La gráfica usa los campos time y value del array recibido por WebSocket.

+
+
+
+ + + + From 16b0c6689d0668a10d98e6451447088b024f90ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Ribal=20del=20R=C3=ADo?= Date: Fri, 13 Mar 2026 09:55:11 +0100 Subject: [PATCH 2/3] feat: add clase eleven --- _quarto.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_quarto.yml b/_quarto.yml index 18580f8..0ecf893 100644 --- a/_quarto.yml +++ b/_quarto.yml @@ -89,6 +89,10 @@ website: >>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) - section: "Bloque IV Comunicación" + contents: + - section: "Semana 11" + contents: + - pages/Bloque4/protocolos.qmd - pages/rubric.qmd From 1e37b0659a9d081364de2c004e1f2cf7ce0fe256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Ribal=20del=20R=C3=ADo?= Date: Fri, 13 Mar 2026 11:58:08 +0100 Subject: [PATCH 3/3] feat: varios --- docs/about.pdf | Bin 15456 -> 15456 bytes docs/index.html | 28 +- docs/index.pdf | Bin 39454 -> 39454 bytes docs/pages/Bloque1/MAcss.html | 30 +- docs/pages/Bloque1/MAcss.pdf | Bin 25003 -> 25003 bytes docs/pages/Bloque1/MAhtml2.html | 30 +- docs/pages/Bloque1/MAhtml2.pdf | Bin 24873 -> 24873 bytes docs/pages/Bloque1/bloque1.html | 30 +- docs/pages/Bloque1/bloque1.pdf | Bin 31789 -> 31789 bytes docs/pages/Bloque1/css.html | 30 +- docs/pages/Bloque1/css.pdf | Bin 73584 -> 73584 bytes docs/pages/Bloque1/entorno.html | 30 +- docs/pages/Bloque1/entorno.pdf | Bin 651786 -> 651786 bytes docs/pages/Bloque1/html.html | 30 +- docs/pages/Bloque1/html.pdf | Bin 737553 -> 737553 bytes docs/pages/Bloque1/t1.html | 30 +- docs/pages/Bloque1/t1.pdf | Bin 34422 -> 34422 bytes docs/pages/Bloque1/t1a.html | 30 +- docs/pages/Bloque1/t1a.pdf | Bin 21362 -> 21362 bytes docs/pages/Bloque1/t2.html | 30 +- docs/pages/Bloque1/t2.pdf | Bin 26835 -> 26835 bytes docs/pages/Bloque1/t2a.html | 30 +- docs/pages/Bloque1/t2a.pdf | Bin 22585 -> 22585 bytes docs/pages/Bloque2/MAclases.html | 30 +- docs/pages/Bloque2/MAclases.pdf | Bin 59342 -> 59342 bytes docs/pages/Bloque2/intensivo.html | 30 +- docs/pages/Bloque2/intensivo.pdf | Bin 76101 -> 76101 bytes docs/pages/Bloque2/jsI.html | 2 +- docs/pages/Bloque2/jsI.pdf | Bin 45005 -> 45005 bytes docs/pages/Bloque2/ti.html | 30 +- docs/pages/Bloque2/ti.pdf | Bin 47646 -> 47646 bytes docs/pages/Bloque2/tia.html | 30 +- docs/pages/Bloque2/tia.pdf | Bin 53898 -> 53898 bytes docs/pages/Bloque3/DOM.html | 30 +- docs/pages/Bloque3/DOM.pdf | Bin 48913 -> 48913 bytes docs/pages/Bloque3/Intermedio.html | 30 +- docs/pages/Bloque3/Intermedio.pdf | Bin 81218 -> 81218 bytes docs/pages/Bloque3/MARef.html | 30 +- docs/pages/Bloque3/MARef.pdf | Bin 33643 -> 33643 bytes docs/pages/Bloque3/MAcss2.html | 30 +- docs/pages/Bloque3/MAcss2.pdf | Bin 25941 -> 25941 bytes docs/pages/Bloque3/MAentorno.html | 2 +- docs/pages/Bloque3/MAentorno.pdf | Bin 20374 -> 20374 bytes docs/pages/Bloque3/ReactI.html | 30 +- docs/pages/Bloque3/ReactI.pdf | Bin 72879 -> 72879 bytes docs/pages/Bloque3/ReactIV.html | 2136 +++++++++-------- docs/pages/Bloque3/ReactIV.pdf | Bin 66753 -> 66753 bytes docs/pages/Bloque3/ps.html | 30 +- docs/pages/Bloque3/ps.pdf | Bin 38383 -> 38383 bytes docs/pages/Bloque3/t10.html | 30 +- docs/pages/Bloque3/t10.pdf | Bin 47016 -> 47016 bytes docs/pages/Bloque3/t6.html | 30 +- docs/pages/Bloque3/t6.pdf | Bin 67533 -> 67533 bytes docs/pages/Bloque4/Protocolos.html | 970 ++++++++ docs/pages/Bloque4/Server.py | 123 + docs/pages/Bloque4/protocolos.html | 1454 ++++++++++++ docs/pages/Bloque4/protocolos.pdf | Bin 0 -> 71068 bytes docs/pages/Bloque4/tester_http_ws_basic.html | 444 ++++ docs/pages/rubric.html | 30 +- docs/rubriuca.pdf | Bin 38680 -> 38682 bytes docs/search.json | 2190 ++++++++++-------- 61 files changed, 6090 insertions(+), 1949 deletions(-) create mode 100644 docs/pages/Bloque4/Protocolos.html create mode 100644 docs/pages/Bloque4/Server.py create mode 100644 docs/pages/Bloque4/protocolos.html create mode 100644 docs/pages/Bloque4/protocolos.pdf create mode 100644 docs/pages/Bloque4/tester_http_ws_basic.html diff --git a/docs/about.pdf b/docs/about.pdf index 5aa0478af364c14c05233b7c310a49cd4dd2b0c1..be621c3c5720aac3d6fb42c4b70ed23f0430e1ac 100644 GIT binary patch delta 106 zcmaD*@t|TuvMGn5v7v#nrHRqxY*T4CXLFzFYF1|#QzK_{S7$d96EkBY7e^x#BSR+> ZQzt`H6E`y_OD79E1sg(2Cf8U$0RSb*94-I= delta 106 zcmaD*@t|TuvMGmwxskDfxqb(DCktmI ZBNsPIQ)ef0V*^(^1sg(2Cf8U$0RS&_9DD!( diff --git a/docs/index.html b/docs/index.html index 84f3bda..e72da4a 100644 --- a/docs/index.html +++ b/docs/index.html @@ -543,8 +543,32 @@ - + + + + + >>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + - -======= - - - ->>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) - - - - - - - -
- + +
+ - -
+ +
-
-
-

React IV

-

Ecosistema npm, React Router, useContext

-
+
+ +
+

React IV

+

Ecosistema npm, React Router, useContext

+
-
+
-
-
Autor/a
-
-

Javier Ribal del Río

+
+
Autor/a
+
+

Javier Ribal del Río

+
-
- -
-
Fecha de publicación
-
-

6 de marzo de 2026

-
-
- -
-
Fecha de última modificación
-
-<<<<<<< HEAD -

7 de marzo de 2026

-======= -

4 de marzo de 2026

->>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) -
-
- -
- + +
+
Fecha de publicación
+
+

6 de marzo de 2026

+
+
+ +
+
Fecha de última modificación
+
+ <<<<<<< HEAD

7 de marzo de 2026

+ ======= +

4 de marzo de 2026

+ >>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) +
+
+ +
-
+
-

Contenido

-
    -
  • Ecosistema React y paquetes npm
  • -
  • Librerías externas
  • -
  • React Router
  • -
  • Parámetros de URL
  • -
  • useContext
  • -
-
-

Ecosistema Node

-

Hasta ahora hemos trabajado únicamente con React y JavaScript.

-

Sin embargo, en el desarrollo real de aplicaciones es muy común utilizar librerías externas, para ello podemos recurrir Node.JS.

-

React está diseñado para funcionar dentro de un ecosistema de paquetes.

-

Ejemplos habituales:

-
    -
  • React Router → navegación
  • -
  • Axios → peticiones HTTP
  • -
  • Chart.js → gráficas
  • -
  • Zustand / Redux → gestión de estado
  • -
  • Librerías de UI: Tailwind, Bootstrap, Booswatch
  • -
-
-
-

npm

-

npm (Node Package Manager) es el sistema que permite instalar y gestionar librerías de JavaScript. Como su nombre indica, está desarrollado por Node.JS

-

Cada proyecto tiene un archivo:

-
package.json
-

En este archivo se registran las dependencias del proyecto.

-

Ejemplo:

-
{
+
+      

Contenido

+
    +
  • Ecosistema React y paquetes npm
  • +
  • Librerías externas
  • +
  • React Router
  • +
  • Parámetros de URL
  • +
  • useContext
  • +
+
+

Ecosistema Node

+

Hasta ahora hemos trabajado únicamente con React y JavaScript.

+

Sin embargo, en el desarrollo real de aplicaciones es muy común utilizar librerías externas, + para ello podemos recurrir Node.JS.

+

React está diseñado para funcionar dentro de un ecosistema de paquetes.

+

Ejemplos habituales:

+
    +
  • React Router → navegación
  • +
  • Axios → peticiones HTTP
  • +
  • Chart.js → gráficas
  • +
  • Zustand / Redux → gestión de estado
  • +
  • Librerías de UI: Tailwind, Bootstrap, Booswatch
  • +
+
+
+

npm

+

npm (Node Package Manager) es el sistema que permite instalar y gestionar librerías de + JavaScript. Como su nombre indica, está desarrollado por Node.JS

+

Cada proyecto tiene un archivo:

+
package.json
+

En este archivo se registran las dependencias del proyecto.

+

Ejemplo:

+
+
+
{
   "dependencies": {
     "react": "^18.0.0",
     "react-router-dom": "^6.0.0"
   }
-}
-
-

Instalación de paquetes

-

Las librerías se instalan desde la terminal.

-
npm install react-router-dom
-

Esto hace tres cosas:

-
    -
  1. Descarga el paquete
  2. -
  3. Lo guarda en node_modules (capreta donde se guardan las librerías externas)
  4. -
  5. Añade la dependencia en package.json
  6. -
-
-
-
-

React Router

-

En una aplicación web tradicional cada enlace carga una página nueva.

-

En React normalmente trabajamos con Single Page Applications (SPA).

-

En una SPA:

-
    -
  • el navegador no recarga la página
  • -
  • React cambia los componentes que se muestran
  • -
-

Para gestionar esto utilizamos React Router.

-

Realmente es la misma página, solo que el usuario lo percibe como distintas páginas

-

El usuario percibirá que el sitio web está divido en diferentes subpáginas

-
    -
  • /
  • -
  • pokemons
  • -
  • pokemons/pikachu
  • -
-
-

Componentes principales de React Router

-

Los elementos fundamentales son:

-
    -
  • BrowserRouter
  • -
  • Routes
  • -
  • Route
  • -
  • Link
  • -
-

Ejemplo básico:

-
import { BrowserRouter, Routes, Route } from "react-router-dom";
+}
+
+
+
+

Instalación de paquetes

+

Las librerías se instalan desde la terminal.

+
+
+
npm install react-router-dom
+
+
+

Esto hace tres cosas:

+
    +
  1. Descarga el paquete
  2. +
  3. Lo guarda en node_modules (capreta donde se guardan las librerías externas)
  4. +
  5. Añade la dependencia en package.json
  6. +
+
+
+
+

React Router

+

En una aplicación web tradicional cada enlace carga una página nueva.

+

En React normalmente trabajamos con Single Page Applications (SPA).

+

En una SPA:

+
    +
  • el navegador no recarga la página
  • +
  • React cambia los componentes que se muestran
  • +
+

Para gestionar esto utilizamos React Router.

+

Realmente es la misma página, solo que el usuario lo percibe como distintas páginas

+

El usuario percibirá que el sitio web está divido en diferentes subpáginas

+
    +
  • /
  • +
  • pokemons
  • +
  • pokemons/pikachu
  • +
+
+

Componentes principales de React + Router

+

Los elementos fundamentales son:

+
    +
  • BrowserRouter
  • +
  • Routes
  • +
  • Route
  • +
  • Link
  • +
+

Ejemplo básico:

+
+
+
import { BrowserRouter, Routes, Route } from "react-router-dom";
 
 function App() {
   return (
@@ -760,54 +976,70 @@ 

Co </BrowserRouter> ); -}

-

Elementos del código

-
    -
  • BrowserRouter
    -Es el componente que activa el sistema de navegación de React Router. Utiliza la API de historial del navegador para cambiar la URL sin recargar la página.
  • -
  • Routes
    -Es el contenedor donde se definen todas las rutas de la aplicación. React Router examina las rutas dentro de este componente para decidir qué componente mostrar.
  • -
  • Route
    -Define una ruta concreta de la aplicación.
  • -
-
    -
  • path
    -Indica la URL que activa la ruta.
    -Ejemplo: / corresponde a la página principal.
  • -
  • element
    -Es el componente de React que se renderiza cuando la URL coincide con el path.
  • -
  • <Home />
    -Componente que se muestra cuando el usuario accede a la ruta /.
  • -
  • <PokemonList />
    -Componente que se muestra cuando el usuario accede a la ruta /pokemons.
  • -
-
- + -
-

Parámetros dinámicos

-

Podemos crear rutas dinámicas.

-

Ejemplo:

-
/pokemon/25
+<Link to="/pokemon">Pokemon</Link>
+
+
+

A diferencia de <a>:

+
    +
  • no recarga la página
  • +
  • React cambia el componente visible
  • +
+
+
+

Parámetros dinámicos

+

Podemos crear rutas dinámicas.

+

Ejemplo:

+
/pokemon/25
 /pokemon/7
-

Definición de la ruta:

-
<Route path="/pokemon/:id" element={<PokemonDetail />} />
-
-

useParams

-

Para acceder al parámetro utilizamos el hook useParams de React Router.

-
import { useParams } from "react-router-dom";
+          

Definición de la ruta:

+
+
+
<Route path="/pokemon/:id" element={<PokemonDetail />} />
+
+
+
+

useParams

+

Para acceder al parámetro utilizamos el hook useParams de React Router.

+
+
+
import { useParams } from "react-router-dom";
 
 function PokemonDetail() {
 
@@ -815,68 +1047,88 @@ 

useParams

return <p>Pokemon {id}</p>; -}
-

Este parámetro puede utilizarse para realizar peticiones a una API.

-
-
-
-
-

Context API

-

En aplicaciones grandes aparece un problema frecuente.

-

Muchos componentes necesitan acceder a la misma información.

-

Por ejemplo:

-
    -
  • usuario
  • -
  • tema visual
  • -
  • idioma
  • -
  • configuración
  • -
-

Si pasamos la información mediante props, los datos deben atravesar muchos componentes.

-

Representación conceptual:

-
App
+}
+ + +

Este parámetro puede utilizarse para realizar peticiones a una API.

+
+ + +
+

Context API

+

En aplicaciones grandes aparece un problema frecuente.

+

Muchos componentes necesitan acceder a la misma información.

+

Por ejemplo:

+
    +
  • usuario
  • +
  • tema visual
  • +
  • idioma
  • +
  • configuración
  • +
+

Si pasamos la información mediante props, los datos deben atravesar muchos componentes.

+

Representación conceptual:

+
App
  └ Layout
     └ Page
        └ Component
-

Si todos necesitan user, debemos pasar la prop continuamente.

-

Este problema se conoce como prop drilling.

-
-

Context

-

React proporciona una solución llamada Context.

-

Context permite compartir información entre múltiples componentes sin pasar props manualmente.

-

El proceso tiene tres pasos:

-
    -
  1. Crear el contexto
  2. -
  3. Proveer el contexto
  4. -
  5. Consumir el contexto
  6. -
-
-

Crear un contexto

-
import { createContext } from "react";
+        

Si todos necesitan user, debemos pasar la prop continuamente.

+

Este problema se conoce como prop drilling.

+
+

Context

+

React proporciona una solución llamada Context.

+

Context permite compartir información entre múltiples componentes sin pasar props + manualmente.

+

El proceso tiene tres pasos:

+
    +
  1. Crear el contexto
  2. +
  3. Proveer el contexto
  4. +
  5. Consumir el contexto
  6. +
+
+

Crear un contexto

+
+
+
import { createContext } from "react";
 
-const UserContext = createContext();
-

Esto crea un contenedor que puede almacenar información compartida.

-
-
-

Provider

-

El Provider permite que los componentes hijos accedan al contexto.

-
<UserContext.Provider value={user}>
+const UserContext = createContext();
+
+
+

Esto crea un contenedor que puede almacenar información compartida.

+
+
+

Provider

+

El Provider permite que los componentes hijos accedan al contexto.

+
+
+
<UserContext.Provider value={user}>
 
   <App />
 
-</UserContext.Provider>
-

Todos los componentes dentro del Provider pueden acceder al valor.

-
-
-

Consumir el contexto

-

Para acceder al contexto utilizamos el hook useContext.

-
import { useContext } from "react";
+</UserContext.Provider>
+
+
+

Todos los componentes dentro del Provider pueden acceder al valor.

+
+
+

Consumir el contexto

+

Para acceder al contexto utilizamos el hook useContext.

+
+
+
import { useContext } from "react";
 
-const user = useContext(UserContext);
-

El componente obtiene directamente el valor almacenado en el contexto.

-
-
-

Ejemplo completo

-
import { createContext, useContext } from "react";
+const user = useContext(UserContext);
+
+
+

El componente obtiene directamente el valor almacenado en el contexto.

+
+
+

Ejemplo completo

+
+
+
import { createContext, useContext } from "react";
 
 const UserContext = createContext();
 
@@ -901,279 +1153,283 @@ 

Ejemplo completo

return <h1>{user.name}</h1>; -}
+}
+
+
-
-
-
+ + + -
- - + } else { + return undefined; + } + }; + var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]'); + for (var i = 0; i < bibliorefs.length; i++) { + const ref = bibliorefs[i]; + const citeInfo = findCites(ref); + if (citeInfo) { + tippyHover(citeInfo.el, function () { + var popup = window.document.createElement('div'); + citeInfo.cites.forEach(function (cite) { + var citeDiv = window.document.createElement('div'); + citeDiv.classList.add('hanging-indent'); + citeDiv.classList.add('csl-entry'); + var biblioDiv = window.document.getElementById('ref-' + cite); + if (biblioDiv) { + citeDiv.innerHTML = biblioDiv.innerHTML; + } + popup.appendChild(citeDiv); + }); + return popup.innerHTML; + }); + } + } + }); + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/docs/pages/Bloque3/ReactIV.pdf b/docs/pages/Bloque3/ReactIV.pdf index 5cc2d463e80fedada89d51b02cce9acc69402e82..bbe3f73cb01c21c58ed39617457c80275b856e6f 100644 GIT binary patch delta 139 zcmX@u$#SrhWy7iO+J?r42F4afX4(dZ>IMetnhN^9`6(`mC8-J;E>=bcMrH=aFeRJ6 zewX8Nb8<3pG<32wHgq;HaWQeSG&43cF*GqSa|NIMetnhN^9`6(`mC8-J;E>=bcMrH=aFeRJ6 zewX8NGca*-b+$Bjb~Sf3H+D9&G&giLG&i!eFfw*=a