Primeros pasos con Supabase: creá tu primera app paso a paso
17 min read

¡Qué bueno que exista Supabase! Es genial para usar como backend en nuestros proyectos web y hacer que todo sea un poco más fácil.
En este artículo te voy a mostrar, paso a paso, cómo crear una aplicación en React que sirve como ejemplo para hacer todo lo necesario con una base de datos de Supabase: cargar datos, mostrarlos en nuestro sitio web, actualizarlos, eliminarlos y todo eso.
Para eso, vamos a crear una app simple que permite listar videos de youtube mediante un link a una web. Los videos se podrán marcar como vistos o no vistos (actualizar), borrarlos y todo lo necesario para aprender a usar Supabase.
Es un proceso simple y, en poco tiempo, vas a saber cómo utilizar Supabase en tu proyecto.
¡Vamos con el paso a paso!
Primer paso: Crear una cuenta en Supabase
Vamos entonces al sitio de Supabase y crear una cuenta si es que aún no lo hiciste, es gratis hacerlo y no necesitas poner datos de una tarjeta de crédito. El proceso de crear una cuenta es rápido y simple.
¿Ya esta lista tu cuenta? Perfecto, seguimos con el segundo paso.
Segundo paso: Crear un proyecto en Supabase
Cuando creas tu cuenta en Supabase, lo primero que hay que hacer es crear una organización. Dentro de esa organización, hay que crear un proyecto.
En mi caso, la organización se llama ondecode y el proyecto lo nombré video manager.
Después, Supabase te va a pedir que configures una contraseña segura. Esta clave es la que protege el acceso a la base de datos, así que tiene sentido usar el botón "Generate a password" que te ofrece la plataforma. Así nos aseguramos de tener una contraseña fuerte y segura.
Por último, hay elegir una región. Lo ideal es seleccionar la que esté más cerca del país en el que te encontrás, para optimizar el rendimiento.
Ahora sí, hay que hacer clic en "Create Project".
Una vez creado el proyecto, deberías poder ver dentro del Project overview las configuraciones generales, algo como esto 👇
Tercer paso: Cómo Configurar Supabase en un proyecto React
Vamos ahora a crear el proyecto de react utilizando vite.
Para ello en tu terminal ejecuta el siguiente comando.
npm create vite@latest
Ahora vamos a ir respondiendo las preguntas para configurar el nombre, el package, el framework y la variante o lenguaje.
npm create vite@latest
◇ Project name:
REACT-SUPABASE
◇ Package name:
package.json
◇ Select a framework:
React
◇ Select a variant:
JavaScript
Como lenguaje opte por JavaScript, para no dejar afuera a quienes no se sienten cómodos con TypeScript.
Luego:
◇ Scaffolding project in .../Desktop/REACT-SUPABASE...
└ Done. Now run:
cd REACT-SUPABASE
npm install
Una ves ejecutado el comando npm install
ya tenemos el proyecto de React creado con sus dependencias instaladas.
Pero Supabase no viene incluido por defecto, así que necesitamos instalarlo manualmente con el siguiente comando:
npm install @supabase/supabase-js
Para conectar nuestra app con Supabase, agregué dos archivos al proyecto:
supabase.js
→ donde vamos a inicializar el cliente de Supabase.env
→ donde guardamos de forma segura nuestras claves de acceso
Así se ve la estructura básica del proyecto: 👇
Empecemos por el primer archivo: .env
.
En este archivo vamos a guardar las claves de nuestro proyecto de Supabase, como SUPABASE_URL
y SUPABASE_KEY
.
Estas son las variables de entorno necesarias para conectar tu app con el backend de Supabase de forma segura.
La SUPABASE_URL
la podés encontrar en la sección Project Overview, justo después de crear tu proyecto. Está identificada como PROJECT URL, hay que copiarla y pegarla en el archivo .env
.
Archivo .env
VITE_SUPABASE_URL=https://dgmtpjufuhzjznaid.supabase.co
Ahora nos queda ir a buscar la SUPABASE_KEY
. Para eso, vamos a Project Settings y, dentro de esa sección, entramos a API Keys.
Presiona "Reveal" para ver la Secret Key, y copiala en el archivo .env
, justo debajo de la variable SUPABASE_URL
.
Archivo .env 👇
VITE_SUPABASE_URL=https://dgmtpjufuhzwjhzznaid.supabase.co
VITE_SUPABASE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.epc3MiOiJzdXBhYmFzZSIsInJlZiI6ImRnbXRwanVmdWh6d2poenpuYWlkIiwicm9sZSI6InNlcnZpY2Vfcm9sImlhdCITkxMCwihwIjoyMDY1ODI1OTEwfQ.wZl7L-BPJ6lD_A0dT0Ra2FKs78
Como estoy usando Vite, a las variables de entorno les agrego el prefijo VITE_
.
Por supuesto, estas claves deben mantenerse seguras y privadas. Justamente por eso las colocamos en el archivo .env
, que no debería compartirse ni subirse a ningún repositorio público.
En mi caso, las muestro únicamente porque se trata de un proyecto de prueba creado específicamente para este artículo, y que va a ser eliminado antes de ser publicado.
Ahora vamos a crear el archivo supabase.js
usando las claves que guardamos en el archivo .env
.
archivo supabase.js👇
import { createClient } from "@supabase/supabase-js";
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL
const supabaseKey = import.meta.env.VITE_SUPABASE_KEY
const supabase = createClient(supabaseUrl,supabaseKey)
export default supabase
Este archivo se encarga de importar e inicializar el cliente de Supabase.
Una vez hecho esto, ya tendremos Supabase listo para usar en cualquier parte de nuestro proyecto React.
Con esto, nuestro proyecto React con Supabase está configurado y listo para seguir avanzando.
Cuarto paso: Cómo crear base de datos en Supabase
Para crear una base de datos en Supabase, vamos al Table Editor dentro de nuestro proyecto. Allí podremos crear nuestras tablas de forma visual y sencilla. 👇
Dentro de Table editor nos vamos a la opción Create a Table y dentro de ella asignamos un nombre y una descripción.
Sin cerrar esa ventana, bajamos un poco y comenzamos a agregar las columnas que formarán nuestra base de datos.
Por defecto ya vienen creadas dos columnas: id
y created_at
Esto es común en bases de datos SQL. En el caso de Supabase se utiliza PostgreSQL
Sumemos entonces dos columnas más a nuestra tabla:
videoLink
con Type: TextisFinished
con Type: Boolean
Estas columnas nos van a servir, por ejemplo, para guardar el enlace de un video (que luego se mostrará como un reproductor en el sitio web) y para saber si el video ya ha sido visto o no.
Importante: en el caso de la columna videoLink
, entramos a sus Settings (clic en el ícono de la tuerca a la derecha) y desactivamos la opción que asigna un valor tipo Null
por defecto cuando no se especifica ninguno.
Esto lo hacemos porque queremos asegurarnos de que, si no se carga un enlace de video, el campo quede vacío y no se muestre ningún reproductor por error en el sitio web.
¡Listo! Solo queda hacer clic en la opción Save, y ya tenemos nuestra base de datos creada y lista para usar.
Nuestro Table Editor ahora se ve así 👇
Quinto paso: Cómo Usar la base de datos de Supabase desde React
Levantamos primero nuestro proyecto de React con el siguiente comando:
npm run dev
Una vez que confirmamos que el proyecto se está ejecutando correctamente en http://localhost:5173
, vamos a limpiar el archivo App.jsx
. Para comenzar a construir nuestra aplicación desde cero e interactuar directamente con la base de datos que creamos en Supabase.
Comencemos armando la estructura 👇
Archivo App.jsx
import supabase from "./supabase"
import './App.css'
import { useState } from "react"
function App() {
const [videoRequest, setVideoRequest] = useState('')
const [videoList, setVideoList] = useState([])
return (
<div>
<h1>VIDEO MANAGER</h1>
<input
type="text"
placeholder="video url"
value={videoRequest}
onChange={(e) => setVideoRequest(e.target.value)}
/>
<button>AGREGAR</button>
</div>
)
}
export default App
Primero importamos Supabase e importamos un poco de CSS para darle algo de estilo. Además, definimos dos estados (hooks) que nos van a servir para gestionar los videos:
videoRequest
: guarda lo que el usuario escribe (la URL del video).videoList
: almacenará la lista de videos agregados, que vamos a ir cargando desde Supabase más adelante.
Te muestro también unos mínimos estilos que deje en App.css
👇
/* CSS correspondiente a todos los elementos usados en el JSX del proyecto */
body {
text-align: center;
}
input {
padding: 0.6em 1em;
margin-right: 0.5em;
border: 1px solid #ccc;
border-radius: 8px;
font-size: 1rem;
width: 60%;
max-width: 400px;
}
button {
padding: 0.6em 1em;
font-size: 1rem;
background-color: #646cff;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
transition: background-color 0.3s ease;
}
button:hover {
background-color: #4b5cd4;
}
/* Lista de videos */
ul.video-list li {
padding: 1rem;
border-radius: 12px;
display: flex;
flex-direction: column;
align-items: center;
max-width: 45rem;
margin: 0 auto;
}
ul.video-list li button {
margin: 0.3rem 0.2rem;
max-width: 40rem;
font-weight: bold;
padding: 1rem;
}
iframe {
border-radius: 12px;
margin-bottom: 1rem;
width: 40rem;
height: 20rem;
max-width: 100%;
}
ul.video-list li button {
margin: 0.3rem 0.2rem;
font-size: 0.9rem;
width: 90%;
}
h1 {
font-size: 2rem;
margin-bottom: 1.5rem;
}
Ahora si, ¡llego el momento! Vamos a crear la función addVideo()
, que es el corazón de esta app. Con esta función vamos a insertar un nuevo dato (la URL del video) en nuestra base de datos en Supabase y luego mostrar ese video directamente en nuestro sitio web.
import supabase from "./supabase"
import './App.css'
import { useState } from "react"
function App() {
const [videoRequest, setVideoRequest] = useState('')
const [videoList, setVideoList] = useState([])
//1. Creamos un nuevo objeto con los datos que queremos insertar en la tabla
const addVideo = async () => {
const newVideo = {
videoLink: videoRequest, // La URL del video que viene del input
isFinished: false // Un campo extra para marcar estado
}
//2. Usamos supabase para insertar el nuevo video en la tabla 'Videos'
const { data, error } = await supabase
.from('Videos') // accede a la tabla 'Videos' en la base de datos
.insert([newVideo]) // inserta un nuevo registro (objeto) en la tabla
.select() // después de insertar el nuevo registro, queremos que nos devuelva los datos del registro insertado.
.single() // espera solo un único resultado (no un array), y lo devuelve como objeto
console.log(newVideo)
console.log(data)
//3. manejo de errores y se agrega nuevo dato al estado local
if (error) {
console.log('error al agregar video', error) // Logueamos el error si algo salió mal
} else {
setVideoList([data, ...videoList]) // Agregamos el nuevo video al estado local
}
setVideoRequest('') // Limpiamos el input
}
return (
<div>
<h1>VIDEO MANAGER</h1>
<input
type="text"
placeholder="video url"
value={videoRequest}
onChange={(e) => setVideoRequest(e.target.value)}
/>
<button onClick={addVideo}>AGREGAR</button>
</div>
)
}
export default App
Estudiemos un poco esta función addVideo()
- Creamos un nuevo objeto con los datos que queremos insertar en la tabla
Las claves videoLink
e isFinished
son los nombres que usamos en nuestro objeto, y coinciden exactamente con los campos que definimos en la tabla Videos
de Supabase. De esta forma todo va a ser mas claro y ordenado.
- Usamos Supabase para insertar el nuevo video en la tabla
Videos
De forma asíncrona, utilizamos los métodos que Supabase nos provee para insertar el nuevo video en la base de datos, y luego le pedimos que nos devuelva el registro insertado para mostrarlo en nuestro sitio.
from('Videos') // Accedemos a la tabla 'Videos' en la base de datos
.insert([newVideo]) // Insertamos un nuevo registro (objeto) en la tabla
.select() // Queremos que nos devuelva los datos del registro insertado
.single() // Esperamos solo un único resultado (no un array), y lo recibimos como objeto
- Manejo de errores y actualización del estado local
Por último, capturamos cualquier error que pueda ocurrir durante el proceso. Si todo sale bien, agregamos el nuevo video que recibimos de Supabase al estado local (videoList), para poder mostrarlo inmediatamente en la interfaz.
Finalmente, limpiamos el input para que quede vacío y listo para ingresar otro video.
La función addVideo()
está asignada al botón “AGREGAR”. Para que todo esto suceda cuando el usuario presiona ese botón
De momento nuestro código esta funcionando, si agregas un link de video en el input va a poder verlo en la base de datos de Supabase. 👇
Cuando Supabase recibe el link que le enviamos por medio del input lo guarda en la tabla y automáticamente le asigna un id único y un campo created_at con la fecha y hora de creación. Estos dos campos vienen por defecto cuando creamos nuestra tabla en Supabase.
En nuestro caso recibimos todo esa información en nuestra data
y la agregamos en nuestro estado local
setVideoList([data, ...videoList]) // Agregamos el nuevo video al estado local
Esa es la diferencia entre data
y newVideo
:
newVideo
es simplemente la información local que creamos antes de enviarla a Supabase.data
es la información que nos devuelve Supabase después de guardar el video, con datos adicionales como elid
generado y el campocreated_at
.
Por lo tanto, ahora simplemente nos queda mostrar los videos de forma correcta en nuestro sitio web.
Además, vamos a agregar la posibilidad de actualizar su estado (isFinished
) y también la opción de eliminar el video.
Para eso, vamos a modificar un poco el return
de nuestro componente y agregar algunos botones para interactuar con cada video. 👇
Sexto paso: Mostrar datos desde Supabase en tu aplicación React
return (
<div>
<h1>VIDEO MANAGER</h1>
<input
type="text"
placeholder="video url"
value={videoRequest}
onChange={(e) => setVideoRequest(e.target.value)}
/>
<button onClick={addVideo}>AGREGAR</button>
<ul className="video-list">
{videoList.map(video => (
//Recorremos la lista de videos para mostrarlos
<li key={video.id}>
{/* iframe para mostrar el video de YouTube.
Detecta si la URL es del tipo youtu.be o youtube.com y extrae el ID del video para incrustarlo */}
<iframe
src={`https://www.youtube.com/embed/${
video.videoLink.includes('youtu.be/')
? video.videoLink.split('youtu.be/')[1].split('?')[0]
: video.videoLink.split('v=')[1]?.split('&')[0]
}`}
></iframe>
{/* Botón para cambiar el estado "visto" del video */}
<button>
{video.isFinished ? 'VISTO' : 'MARCAR VISTO'}
</button>
{/* Botón para eliminar el video de la base de datos y del estado local */}
<button>BORRAR</button>
</li>
))}
</ul>
</div>
)
Nota rapida sobre el iframe
Para incrustar correctamente el video de YouTube, se hace necesario manejar dos tipos de URLs que los usuarios pueden copiar: la URL directa desde el navegador (youtube.com/watch?v=
...
) y la que se obtiene al hacer clic en el botón "Compartir" (youtu.be/
...
).
Por eso usamos métodos como .includes()
, .split()
y una lógica condicional sencilla para extraer el ID del video de forma limpia. Así adaptamos la URL al formato que requiere la etiqueta <iframe>
y evitamos errores que puedan romper nuestra web.
Por último, agregamos dos botones por cada video:
<button>{video.isFinished ? 'VISTO' : 'MARCAR VISTO'}</button>
: Este botón le permitira al usuario alternar el estadoisFinished
del video. Según el valor de ese estado, se mostrará el texto correspondiente.<button>BORRAR</button>
: El boton que va a eliminar el video tanto de Supabase como del estado local.
Con esto tenemos todo listo para poder visualizar los videos. en nuestra web, solo que no aun no los estamos trayendo desde la base de datos de Supabase.
Vamos a hacerlos ahora con un simple useEffect 👇
//importar el useEffect
import { useState, useEffect } from "react"
//utilizamos la funcion fetchvideos dentro del useEffect
useEffect(() => {
fetchVideos()
}, [])
// funcion para traer los videos de suapabse a nuestra web
const fetchVideos = async () => {
const { data, error } = await supabase //de forma asyncrona caputramos la data(videos) o un posible error
.from("Videos") // accede a la tabla "Videos" en Supabase
.select("*"); // selecciona todos los registros y columnas
if (error) {
console.log("Error: ", error);
} else {
setVideoList(data);
}
};
La función fetchVideos
accede con .from
a la tabla "Videos"
de la base de datos de Supabase, y con .select("*")
trae todos los registros.
Luego, si no ocurre ningún error, esos datos se guardan en el estado videoList
usando setVideoList
.
Ese videoList
es justamente lo que recorremos más adelante con .map()
dentro del return
, para mostrar los videos en nuestra web.
Algo así se vería nuestro proyecto hasta ahora 👇
Para mayor contexto te dejo el código completo tal como lo tenemos hasta ahora.
import supabase from "./supabase"
import './App.css'
import { useState, useEffect } from "react"
function App() {
const [videoRequest, setVideoRequest] = useState('')
const [videoList, setVideoList] = useState([])
useEffect(() => {
fetchVideos()
}, [])
const fetchVideos = async () => {
const { data, error } = await supabase
.from("Videos")
.select("*");
if (error) {
console.log("Error: ", error);
} else {
setVideoList(data);
}
};
const addVideo = async () => {
const newVideo = {
videoLink: videoRequest,
isFinished: false
}
const { data, error } = await supabase
.from('Videos') // accede a la tabla 'Videos' en la base de datos
.insert([newVideo]) // inserta un nuevo registro (objeto) en la tabla
.select() // después de insertar el nuevo registro, queremos que nos devuelva los datos del registro insertado.
.single() // espera solo un único resultado (no un array), y lo devuelve como objeto
console.log(newVideo)
console.log(data)
if (error) {
console.log('error al agregar video', error)
} else {
setVideoList([data, ...videoList])
}
setVideoRequest('')
}
return (
<div>
<h1>VIDEO MANAGER</h1>
<input
type="text"
placeholder="video url"
value={videoRequest}
onChange={(e) => setVideoRequest(e.target.value)}
/>
<button onClick={addVideo}>AGREGAR</button>
<ul className="video-list">
//Recorremos la lista de videos para mostrarlos
{videoList.map(video => (
<li key={video.id}>
//iframe para mostrar el video de YouTube.
//Detecta si la URL es del tipo youtu.be o youtube.com y extrae el ID del video para incrustarlo
<iframe
src={`https://www.youtube.com/embed/${
video.videoLink.includes('youtu.be/')
? video.videoLink.split('youtu.be/')[1].split('?')[0]
: video.videoLink.split('v=')[1]?.split('&')[0]
}`}
></iframe>
//Botón para cambiar el estado "visto" del video
<button>
{video.isFinished ? 'VISTO' : 'MARCAR VISTO'}
</button>
//Botón para eliminar el video de la base de datos y del estado local
<button>BORRAR</button>
</li>
))}
</ul>
</div>
)
}
export default App
Bueno, vamos poco a poco terminando, nos quedan simplemente dos cosas más: Actualizar el estado del video si ya fue visto (y guardar ese cambio en Supabase), y también la posibilidad de eliminar videos de nuestro sitio web y de Supabase.
Séptimo paso: Cómo actualizar el estado de un video en Supabase
¿El video ya fue marcado como visto o no? Eso es algo que le tenemos que avisar a Supabase.
Así que vamos a armar la función justo acá abajo 👇
//UPDATE
const toggleDone = async (id, isFinished) => {
const { error } = await supabase
.from('Videos')
.update({ isFinished: !isFinished })
.eq('id', id);
if (error) {
console.error('Error actualizando video:', error);
} else {
setVideoList(videoList.map(v =>
v.id === id ? { ...v, isFinished: !v.isFinished } : v
));
}
};
//en nuestro boton aregamos la funcion
{/* Botón para cambiar el estado "visto" del video */}
<button onClick={() => toggleDone(video.id, video.isFinished)}>
{video.isFinished ? 'VISTO' : 'MARCAR VISTO'}
</button>
Con esta función toggleDone, lo que hacemos es avisarle a Supabase que el estado del video cambió (si fue visto o no).
Primero usamos .from('Videos')
para decirle a Supabase en qué tabla queremos trabajar. En este caso, nuestra tabla se llama "Videos".
Después viene .update({ isFinished: !isFinished })
, que básicamente invierte el valor actual del campo isFinished. Si estaba en true, lo pasa a false, y viceversa.
Con .eq('id', id)
le indicamos exactamente qué fila (qué video) queremos actualizar. Es como decirle: "buscá el video con este id y actualizalo".
Si todo sale bien, usamos setVideoList(...)
para actualizar el estado local en React y que la interfaz también muestre el cambio sin necesidad de refrescar.
Por último, le pasamos la función al botón que se encarga de actualizar el estado cuando se hace click, y le indicamos que muestre “VISTO” o “MARCAR VISTO” según corresponda.
Bueno, lo último que nos queda es eliminar entonces, ya vamos terminando.
Octavo paso: Cómo eliminar el estado de un video en Supabase
//DELETE
const deleteVideo = async (id) => {
const { error } = await supabase
.from('Videos')
.delete()
.eq('id', id);
if (error) {
console.error('Error eliminando video:', error);
} else {
// Solo actualiza el estado si la eliminación fue exitosa
setVideoList(videoList.filter(video => video.id !== id));
}
};
{/* Botón para eliminar el video de la base de datos y del estado local */}
<button onClick={() => deleteVideo(video.id)}>BORRAR</button>
Ahora vamos con la función para eliminar un video. Es muy parecida a la de actualizar, pero en vez de usar .update()
, usamos .delete().
Con .from('Videos')
le decimos a Supabase que queremos trabajar en la tabla “Videos”
. Luego.delete()
para indicarle que queremos borrar un registro de la base de datos. Y con .eq('id', id)
especificamos cuál video eliminar, usando su id.
Si no hay errores, actualizamos el estado local con setVideoList, pero esta vez filtrando la lista para sacar el video que borramos. Así desaparece inmediatamente de la interfaz.
Para que el usuario pueda borrar un video, agregamos un botón con un onClick que llama a esta función y le pasa el id del video correspondiente.
Con esto entonces, ya hemos finalizado este proyecto con Supabase, quiero dejarte ahora el código completo para mayor claridad 👇
import supabase from "./supabase"
import './App.css'
import { useState, useEffect } from "react"
function App() {
const [videoRequest, setVideoRequest] = useState('')
const [videoList, setVideoList] = useState([])
useEffect(() => {
fetchVideos()
}, [])
const fetchVideos = async () => {
const { data, error } = await supabase
.from("Videos")
.select("*");
if (error) {
console.log("Error: ", error);
} else {
setVideoList(data);
}
};
//AGREGAR VIDEOS
const addVideo = async () => {
const newVideo = {
videoLink: videoRequest,
isFinished: false
}
const { data, error } = await supabase
.from('Videos') // accede a la tabla 'Videos' en la base de datos
.insert([newVideo]) // inserta un nuevo registro (objeto) en la tabla
.select() // después de insertar el nuevo registro, queremos que nos devuelva los datos del registro insertado.
.single() // espera solo un único resultado (no un array), y lo devuelve como objeto
console.log(newVideo)
console.log(data)
if (error) {
console.log('error al agregar video', error)
} else {
setVideoList([data, ...videoList])
}
setVideoRequest('')
}
//UPDATE
const toggleDone = async (id, isFinished) => {
const { error } = await supabase
.from('Videos') // Asegurate también de que esta tabla se llame "Videos", no "videoTest"
.update({ isFinished: !isFinished })
.eq('id', id);
if (error) {
console.error('Error actualizando video:', error);
} else {
setVideoList(videoList.map(v =>
v.id === id ? { ...v, isFinished: !v.isFinished } : v
));
}
};
//DELETE
const deleteVideo = async (id) => {
const { error } = await supabase
.from('Videos')
.delete()
.eq('id', id);
if (error) {
console.error('Error eliminando video:', error);
} else {
// Solo actualiza el estado si la eliminación fue exitosa
setVideoList(videoList.filter(video => video.id !== id));
}
};
return (
<div>
<h1>VIDEO MANAGER</h1>
<input
type="text"
placeholder="video url"
value={videoRequest}
onChange={(e) => setVideoRequest(e.target.value)}
/>
<button onClick={addVideo}>AGREGAR</button>
<ul className="video-list">
{videoList.map(video => (
//Recorremos la lista de videos para mostrarlos
<li key={video.id}>
{/* iframe para mostrar el video de YouTube.
Detecta si la URL es del tipo youtu.be o youtube.com y extrae el ID del video para incrustarlo */}
<iframe
src={`https://www.youtube.com/embed/${
video.videoLink.includes('youtu.be/')
? video.videoLink.split('youtu.be/')[1].split('?')[0]
: video.videoLink.split('v=')[1]?.split('&')[0]
}`}
></iframe>
{/* Botón para cambiar el estado "visto" del video */}
<button onClick={() => toggleDone(video.id, video.isFinished)}>
{video.isFinished ? 'VISTO' : 'MARCAR VISTO'}
</button>
{/* Botón para eliminar el video de la base de datos y del estado local */}
<button onClick={() => deleteVideo(video.id)}>BORRAR</button>
</li>
))}
</ul>
</div>
)
}
export default App
Muchas gracias por leerme y espero que te haya servido!
Saludos!
Pablo.