Tutorial de Tauri – Capítulo 5: Integración con React

Hasta ahora hemos trabajado con HTML, CSS y JavaScript puro. Funciona bien para cosas sencillas, pero para aplicaciones más complejas necesitas herramientas más potentes. React es el framework más popular y se integra perfectamente con Tauri.

Crear un proyecto Tauri con React

El proceso es casi idéntico al capítulo anterior, pero eligiendo React como template:

npm create tauri-app@latest

Responde a las preguntas:

  • Project name: tauri-react-app
  • Identifier: com.tutorial.taurireact
  • Frontend language: TypeScript / JavaScript
  • Package manager: npm
  • UI template: React
  • UI flavor: JavaScript

Instala las dependencias y ejecuta:

cd tauri-react-app
npm install
npm run tauri dev

Verás la aplicación React por defecto ejecutándose como app de escritorio.

Estructura del proyecto React

La carpeta src/ ahora tiene la estructura típica de React:

src/
├── App.jsx          # Componente principal
├── App.css          # Estilos del componente
├── main.jsx         # Punto de entrada de React
└── assets/          # Imágenes y recursos

React en 5 minutos: lo esencial

Si vienes de Angular o JavaScript vanilla, React puede parecer extraño al principio. Vamos a explicar los conceptos básicos que necesitas para este tutorial.

¿Qué es un componente?

Un componente en React es simplemente una función que devuelve HTML (bueno, técnicamente JSX, que es HTML con superpoderes). Piensa en los componentes como piezas de LEGO: creas piezas pequeñas y las combinas para construir tu aplicación.

Este es el componente más simple posible:

function Saludo() {
  return <h1>Hola mundo</h1>;
}

export default Saludo;

Y así lo usarías en otro archivo:

import Saludo from "./Saludo";

function App() {
  return <Saludo />;
}

¿Ves? <Saludo /> se usa como si fuera una etiqueta HTML. Esa es la magia de React: creas tus propias «etiquetas» reutilizables.

¿Qué es el estado (state)?

El estado son los datos que pueden cambiar en tu componente. Cuando el estado cambia, React actualiza automáticamente lo que se ve en pantalla.

En JavaScript vanilla harías algo así:

let contador = 0;
document.getElementById("contador").textContent = contador;
// Cada vez que cambia, tienes que actualizar el DOM manualmente

En React, el estado se actualiza solo:

const [contador, setContador] = useState(0);
// Cuando llamas setContador(5), React actualiza la pantalla automáticamente

¿Qué es useState?

useState es un hook (gancho) de React que te permite añadir estado a un componente. La sintaxis es:

const [valor, setValor] = useState(valorInicial);

Devuelve dos cosas:

  • valor: el dato actual
  • setValor: una función para cambiar ese dato

Por ejemplo:

const [nombre, setNombre] = useState("");        // Empieza vacío
const [edad, setEdad] = useState(25);            // Empieza en 25
const [activo, setActivo] = useState(false);     // Empieza en false

Cuando quieres cambiar el valor, llamas a la función set:

setNombre("Eduardo");  // Ahora nombre vale "Eduardo"
setEdad(30);           // Ahora edad vale 30

Crear un componente personalizado

Ahora que entiendes los conceptos, vamos a crear algo útil. Crea un archivo src/Greeting.jsx:

import { useState } from "react";

function Greeting() {
  const [name, setName] = useState("");
  const [greeting, setGreeting] = useState("");

  function handleSubmit(e) {
    e.preventDefault();
    setGreeting(`¡Hola, ${name}! Bienvenido a Tauri con React.`);
  }

  return (
    <div className="greeting-container">
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          placeholder="Escribe tu nombre"
          value={name}
          onChange={(e) => setName(e.target.value)}
        />
        <button type="submit">Saludar</button>
      </form>
      
      {greeting && <p className="greeting-message">{greeting}</p>}
    </div>
  );
}

export default Greeting;

Explicación del código línea por línea

Línea 1: Importamos useState de React para poder usar estado.

Líneas 4-5: Creamos dos estados:

  • name: guarda lo que el usuario escribe en el input
  • greeting: guarda el mensaje de saludo que mostraremos

Líneas 7-10: La función handleSubmit se ejecuta cuando el usuario envía el formulario. e.preventDefault() evita que la página se recargue (comportamiento por defecto de los formularios). Luego actualizamos el estado greeting con el mensaje personalizado.

Línea 16: El input tiene value={name} para mostrar el valor actual, y onChange para actualizar el estado cada vez que el usuario escribe algo.

Línea 22: {greeting && ...} es un truco de React: solo muestra el párrafo si greeting tiene contenido. Si está vacío, no muestra nada.

Usar el componente

Modifica App.jsx para usarlo:

import "./App.css";
import Greeting from "./Greeting";

function App() {
  return (
    <div className="container">
      <h1>Mi App Tauri + React</h1>
      <Greeting />
    </div>
  );
}

export default App;

Añadir los estilos

Añade estos estilos en App.css:

.container {
  max-width: 600px;
  margin: 0 auto;
  padding: 2rem;
  text-align: center;
}

h1 {
  color: #24c8db;
  margin-bottom: 2rem;
}

.greeting-container {
  background: #1a1a1a;
  padding: 2rem;
  border-radius: 12px;
}

.greeting-container form {
  display: flex;
  gap: 1rem;
  justify-content: center;
}

.greeting-container input {
  padding: 0.8rem 1rem;
  border: 1px solid #444;
  border-radius: 8px;
  background: #2a2a2a;
  color: white;
  font-size: 1rem;
}

.greeting-container button {
  padding: 0.8rem 1.5rem;
  background: #24c8db;
  color: #1a1a1a;
  border: none;
  border-radius: 8px;
  font-weight: bold;
  cursor: pointer;
}

.greeting-message {
  margin-top: 1.5rem;
  font-size: 1.2rem;
  color: #24c8db;
}

Usar la API de Tauri desde React

Hasta ahora solo hemos usado React. Ahora vamos a conectar con Tauri para acceder a funcionalidades del sistema.

La API de Tauri ya está disponible con el paquete @tauri-apps/api. Vamos a modificar el componente para que el saludo venga de Rust (lo haremos en el próximo capítulo) pero primero veamos cómo importar la API:

import { invoke } from "@tauri-apps/api/core";

Esta función invoke es la que usarás para llamar a funciones de Rust desde JavaScript. La veremos en detalle en el siguiente capítulo.

Hooks personalizados (opcional)

Esta sección es opcional y algo más avanzada. Si estás empezando con React, puedes saltártela y volver más adelante.

¿Qué es un hook personalizado?

Ya conoces useState, que es un hook que viene con React. Pero también puedes crear los tuyos propios. Un hook personalizado es simplemente una función que empieza por use y que puede usar otros hooks dentro.

¿Para qué sirven? Para reutilizar lógica entre componentes. Si tienes la misma lógica en varios sitios, la extraes a un hook.

Ejemplo práctico

Imagina que en varios componentes necesitas la lógica de «saludar». En vez de repetir el código, creas un hook. Crea el archivo src/hooks/useGreeting.js:

import { useState } from "react";

export function useGreeting() {
  const [greeting, setGreeting] = useState("");
  const [loading, setLoading] = useState(false);

  async function greet(name) {
    setLoading(true);
    // Aquí llamaremos a Rust más adelante
    setGreeting(`¡Hola, ${name}!`);
    setLoading(false);
  }

  return { greeting, loading, greet };
}

Ahora cualquier componente puede usar este hook:

import { useGreeting } from "./hooks/useGreeting";

function MiComponente() {
  const { greeting, loading, greet } = useGreeting();
  
  return (
    <div>
      <button onClick={() => greet("Eduardo")}>Saludar</button>
      {loading ? <p>Cargando...</p> : <p>{greeting}</p>}
    </div>
  );
}

La ventaja es que la lógica está en un solo lugar. Si mañana quieres cambiar cómo funciona el saludo, solo modificas el hook y todos los componentes que lo usan se actualizan.

Organizar componentes

A medida que tu aplicación crezca, querrás organizar mejor los archivos. Una estructura común es:

src/
├── components/
│   ├── Greeting/
│   │   ├── Greeting.jsx
│   │   └── Greeting.css
│   └── Header/
│       ├── Header.jsx
│       └── Header.css
├── hooks/
│   └── useGreeting.js
├── App.jsx
└── main.jsx

Cada componente tiene su propia carpeta con su archivo JSX y CSS. Esto mantiene el código organizado cuando tienes muchos componentes.

Hot Reload en acción

Una de las ventajas de usar React con Tauri es el hot reload. Mientras tienes npm run tauri dev ejecutándose:

  • Los cambios en React se reflejan instantáneamente
  • Los cambios en CSS se aplican sin recargar
  • Los cambios en Rust requieren recompilación (automática)

Esto hace que el desarrollo sea rápido y fluido.

Resumen

En este capítulo has aprendido a:

  • Crear un proyecto Tauri con React
  • Entender qué son los componentes y el estado en React
  • Usar useState para manejar datos que cambian
  • Crear componentes React personalizados
  • Importar la API de Tauri
  • Crear hooks personalizados (opcional)
  • Organizar tu código

En el próximo capítulo aprenderás las bases de Rust que necesitas para empezar a escribir código del backend. No te preocupes: solo veremos lo justo y necesario, siempre con comparaciones con JavaScript para que te resulte familiar.

Nos vemos en el Capítulo 6.


¿Te está gustando este tutorial?

Este tutorial forma parte del libro Tauri 2.0: Aplicaciones de Escritorio con React y Rust, disponible en Amazon en formato papel y ebook. El libro incluye todos los capítulos, tres proyectos completos paso a paso y contenido exclusivo que no encontrarás en el blog.

Un saludo, y si aún no lo has hecho no olvides suscribirte a mi blog para no perderte los próximos posts  :-),

También puedes seguirme en Twitter en ‎@revi_apps y no olvides que me ayudas mucho si compartes este post en las redes sociales.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Scroll al inicio