<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ crud - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Descubre miles de cursos de programación escritos por expertos. Aprende Desarrollo Web, Ciencia de Datos, DevOps, Seguridad y obtén asesoramiento profesional para desarrolladores. ]]>
        </description>
        <link>https://www.freecodecamp.org/espanol/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ crud - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/espanol/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 14 May 2026 19:58:39 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/espanol/news/tag/crud/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Cómo construir una aplicación CRUD usando React y Convex ]]>
                </title>
                <description>
                    <![CDATA[ Las operaciones CRUD son la base de cada aplicación, por lo que es esencial volverse competente en esto cuando se aprende nuevas tecnologías. En este tutorial, aprenderás cómo construir una aplicación CRUD usando React y Convex. Cubriremos estas operaciones al construir un proyecto que se llama Book Collections. En este ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/como-construir-una-aplicacion-crud-usando-react-y-convex/</link>
                <guid isPermaLink="false">68102fd4c8db8f04fae91582</guid>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ convex ]]>
                    </category>
                
                    <category>
                        <![CDATA[ crud ]]>
                    </category>
                
                    <category>
                        <![CDATA[ full stack ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Elias Ezequiel Pereyra Gomez ]]>
                </dc:creator>
                <pubDate>Fri, 27 Jun 2025 01:18:13 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2025/04/Captura-desde-2025-04-28-22-49-09.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Las operaciones CRUD son la base de cada aplicación, por lo que es esencial volverse competente en esto cuando se aprende nuevas tecnologías.</p><p>En este tutorial, aprenderás cómo construir una aplicación CRUD usando React y Convex. Cubriremos estas operaciones al construir un proyecto que se llama Book Collections. En este proyecto, los usuarios serán capaz de agregar libros y actualizar sus estados una vez que completan un libro.</p><h2 id="tabla-de-contenido"><strong><strong>Tabl</strong>a<strong> </strong>de<strong> </strong>Contenido</strong></h2><!--kg-card-begin: markdown--><ul>
<li><a href="#que-es-convex">¿Qué es Convex?</a></li>
<li><a href="#como-configurar-proyecto">¿Cómo configurar tu proyecto?</a></li>
<li><a href="#como-crear-esquema">¿Cómo crear el esquema?</a></li>
<li><a href="#como-crear-ui">¿Cómo crear la UI?</a></li>
<li><a href="#como-crear-funciones-crud">¿Cómo crear las funciones CRUD?</a></li>
<li><a href="#estilos">Los estilos</a></li>
<li><a href="#resumen">Resumen</a></li>
</ul>
<!--kg-card-end: markdown--><!--kg-card-begin: html--><h2 id="que-es-convex">¿Qué es Convex?</h2><!--kg-card-end: html--><p>Convex es la Plataforma BaaS que simplifica el desarrollo backend. Convex viene con una base de datos de tiempo real, y no tienes que preocuparte sobre escribir lógica de parte del servidor de forma separada porque provee métodos para solicitar y mutar la base de datos.</p><h3 id="pre-requisitos"><strong><strong>Pre</strong>-requisitos</strong></h3><p>Para seguir este tutorial, debes conocer los fundamentos de React. Estaré usando TypeScript en este proyecto, pero es opcional, así que puedes seguirme con JavaScript.</p><!--kg-card-begin: html--><h2 id="como-configurar-proyecto">Cómo configurar tu proyecto</h2><!--kg-card-end: html--><p>Crea una carpeta separa para el proyecto y llámalo como gustes – yo lo llamaré <strong>Books</strong>. Configuraremos Convex y React en esa carpeta.</p><p>Puedes crear una aplicación de React usando este comando:</p><pre><code class="language-bash">npm create vite@latest my-app -- --template react-ts
</code></pre><p>Si quieres trabajar con JavaScript, entonces quita el `ts` al final. Sería:</p><pre><code class="language-bash">npm create vite@latest my-app -- --template react
</code></pre><h3 id="c-mo-configurar-convex"><strong>Cómo configurar<strong> Convex</strong></strong></h3><p>Tenemos que instalar Convex en la misma carpeta. Puedes hacer eso usando este comando:</p><pre><code class="language-bash">npm install convex
</code></pre><p>Luego, ejecuta <code>npx convex dev</code>. Si lo estás haciendo por primera vez, te debería pedirte la autenticación. De otra forma, debería preguntarte por el nombre del proyecto.</p><p>Puedes visitar el <a href="https://www.convex.dev/">panel de Convex</a> para ver el proyecto que has creado.</p><p>Ahora que hemos configurado Convex y React, necesitamos conectar el backend de Convex a la aplicación de React.</p><p>En el <strong><code>src/main.tsx</code>, </strong>envuelve tu componente <code>App</code> con <code>ConvexReactClient</code>:</p><pre><code class="language-tsx">import { createRoot } from "react-dom/client";
import App from "./App.tsx";
import { ConvexProvider, ConvexReactClient } from "convex/react";
import "./index.css"

const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string);

createRoot(document.getElementById("root")!).render(
  &lt;ConvexProvider client={convex}&gt;
    &lt;App /&gt;
  &lt;/ConvexProvider&gt;
);
</code></pre><p>Cuando configuras Convex, se crea un archivo <code>.env.local</code>. Puedes ver el URL de tu backend en ese archivo.</p><p>En la línea de abajo, instanciamos el Cliente de Convex de React con el URL.</p><pre><code class="language-typescript">const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string);
</code></pre><!--kg-card-begin: html--><h2 id="como-crear-esquema">Cómo crear el Esquema</h2><!--kg-card-end: html--><p>En tu carpeta principal del proyecto, deberías de ver la carpeta <strong>convex</strong>. Manejaremos las solicitudes de la base de datos y las mutaciones aquí.</p><p>Crea un archivo <strong>schema.ts</strong> en la carpeta <strong>convex:</strong></p><pre><code class="language-typescript">import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";

export default defineSchema({
  books: defineTable({
    title: v.string(),
    author: v.string(),
    isCompleted: v.boolean(),
  }),
});
</code></pre><p>Puedes definir un Esquema para tu documento con <code>defineSchema</code> y crea un tabla con <code>defineTable</code>. Convex provee estas funciones para definir un esquema y crear una tabla.</p><p><code>v</code> es el validador de tipo, se usa para proveer tipos para cada dato que agregamos a la tabla.</p><p>Para este proyecto, ya que es una aplicación de colección de libros, la estructura tendrá <code>title</code>, <code>author</code>, y <code>isCompleted</code>. Puedes agregar mas campos.</p><p>Ahora que tienes definido tu esquema, configuremos la UI básica en React.</p><!--kg-card-begin: html--><h2 id="como-crear-ui">Cómo crear la UI</h2><!--kg-card-end: html--><p>En la carpeta <strong>src</strong>, crea una carpeta llamada <strong>component</strong> y un archivo <strong>Home.tsx</strong>. Aquí, puedes definir la UI.</p><pre><code class="language-tsx">import { useState } from "react";
import "../styles/home.css";

const Home = () =&gt; {
  const [title, setTitle] = useState("");
  const [author, setAuthor] = useState("");
  return (
    &lt;div className="main-container"&gt;
      &lt;h1&gt;Book Collections&lt;/h1&gt;
      &lt;form onSubmit={handleSubmit}&gt;
        &lt;input
          type="text"
          name="title"
          value={title}
          onChange={(e) =&gt; setTitle(e.target.value)}
          placeholder="book title"
        /&gt;
        &lt;br /&gt;
        &lt;input
          type="text"
          name="author"
          value={author}
          onChange={(e) =&gt; setAuthor(e.target.value)}
          placeholder="book author"
        /&gt;
        &lt;br /&gt;
        &lt;input type="submit" /&gt;
      &lt;/form&gt;
      {books ? &lt;Books books={books} /&gt; : "Loading..."}
    &lt;/div&gt;
  );
};

export default Home;
</code></pre><p>Puedes crear tu componente como gustes. Agregué dos campos input <code>title</code>, <code>author</code>, y un botón <code>submit</code>. Esta es la estructura básica. Ahora podemos crear los métodos CRUD en el backend.</p><!--kg-card-begin: html--><h2 id="como-crear-funciones-crud">Cómo crear las funciones CRUD</h2><!--kg-card-end: html--><p>En la carpeta <strong>convex</strong>, puedes crear un archivo <strong>queries.ts</strong> separado para las funciones CRUD.</p><h3 id="la-funci-n-create"><strong>La<strong> </strong>Función Create</strong></h3><p>Ie <strong><strong>convex/queries.ts</strong></strong>:</p><p>Puedes definir una función <code>createBooks</code>. Puedes usar la función <code>mutation</code> de Convex para crear, actualizar, y eliminar datos. Leer los datos será a través de <code>query</code>.</p><p>La función <code>mutation</code> espera estos argumentos:</p><ul><li><code>agrs</code>: los datos que necesitamos almacenar en la base de datos.</li><li><code>handler</code>: maneja la lógica para almacenar los datos en la base de datos. El <code>handler</code> es una función asíncrona, y tiene dos argumentos: <code>ctx</code> y <code>args</code>. Aquí, <code>ctx</code> es el objeto contexto que usaremos para manejar las operaciones de la base de datos.</li></ul><p>Usarás el método <code>insert</code> para ingresar nuevos datos. El primer parámetro en el <code>insert</code> es el nombre de la tabla y el segundo es para los datos que necesitan ser insertados.</p><p>Como último, puedes regresar los datos desde la base de datos.</p><p>Aquí estás el código:</p><pre><code class="language-typescript">import { mutation} from "./_generated/server";
import { v } from "convex/values";

export const createBooks = mutation({
  args: { title: v.string(), author: v.string() },
  handler: async (ctx, args) =&gt; {
    const newBookId = await ctx.db.insert("books", {
      title: args.title,
      author: args.author,
      isCompleted: false,
    });
    return newBookId;
  },
});
</code></pre><h3 id="la-funci-n-read"><strong>La Función <strong>Read</strong></strong></h3><p>En <strong><strong>convex/queries.ts</strong></strong>:</p><pre><code class="language-typescript">import { query } from "./_generated/server";
import { v } from "convex/values";

//read
export const getBooks = query({
  args: {},
  handler: async (ctx) =&gt; {
    return await ctx.db.query("books").collect();
  },
});
</code></pre><p>En esta operación read, usamos la función incorporada <code>query</code> de Convex. Aquí, <code>args</code> estará vacía ya que no obtenemos ningún datos del usuario. De forma similar, la función <code>handler</code> es asíncrona y usa el objeto <code>ctx</code> para solicitar de la base de datos y regresar los datos.</p><h3 id="la-funci-n-update"><strong>La Función <strong>Update</strong></strong></h3><p>En <strong><strong>convex/queries.ts</strong></strong>:</p><p>Crea una función <code>updateStatus</code>. Vamos a actualizar solamente el estado <code>isCompleted</code>.</p><p>Aquí, necesitas obtener el ID del documento y el estado del usuario. En el <code>args</code>, definiremos el <code>id</code> y el <code>isCompleted</code>, los cuales vendrán del usuario.</p><p>En el <code>handler</code>, usaremos el método <code>patch</code> para actualizar los datos. El método <code>patch</code> espera dos argumentos: el primer argumento es el <code>id</code> del documento y el segundo es para los datos actualizados.</p><pre><code class="language-typescript">import { mutation } from "./_generated/server";
import { v } from "convex/values";

//update
export const updateStatus = mutation({
  args: { id: v.id("books"), isCompleted: v.boolean() },
  handler: async (ctx, args) =&gt; {
    const { id } = args;
    await ctx.db.patch(id, { isCompleted: args.isCompleted });
    return "updated"
  },
});
</code></pre><h3 id="funci-n-delete"><strong>Función <strong>Delete</strong></strong></h3><p>En <strong><strong>convex/queries.ts</strong></strong>:</p><p>Crea una función <code>deleteBooks</code> y usa la función <code>mutation</code>. Necesitaremos el ID del documento para que se elimine. En el <code>args</code>, define un ID. En el <code>handler</code>, usa el método <code>delete</code> del objeto <code>ctx</code>, y pasa el ID. Esto eliminará el documento.</p><pre><code class="language-typescript">import { mutation } from "./_generated/server";
import { v } from "convex/values";

//delete
export const deleteBooks = mutation({
  args: { id: v.id("books") },
  handler: async (ctx, args) =&gt; {
    await ctx.db.delete(args.id);
    return "deleted";
  },
});
</code></pre><p>A partir de ahora, has completado las funciones CRUD en el backend. Ahora necesitamos hacerlo funcionar en el UI. Volvamos a React.</p><h3 id="actualizar-el-ui"><strong>Actualizar<strong> </strong>el<strong> UI</strong></strong></h3><p>Ya has creado un UI básico en la aplicación de React, con algunos campos input. Vamos a actualizarlo.</p><p>En <strong><strong>src/component/Home.tsx</strong></strong>:</p><pre><code class="language-tsx">import { useQuery, useMutation } from "convex/react";
import { api } from "../../convex/_generated/api";
import { Books } from "./Books";
import { useState } from "react";
import "../styles/home.css";

const Home = () =&gt; {
  const [title, setTitle] = useState("");
  const [author, setAuthor] = useState("");
  const books = useQuery(api.queries.getBooks);
  const createBooks = useMutation(api.queries.createBooks);

  const handleSubmit = (e: React.FormEvent&lt;HTMLFormElement&gt;): void =&gt; {
    e.preventDefault();
    createBooks({ title, author })
      .then(() =&gt; {
        console.log("created");
        setTitle("");
        setAuthor("");
      })
      .catch((err) =&gt; console.log(err));
  };
  return (
    &lt;div className="main-container"&gt;
      &lt;h1&gt;Book Collections&lt;/h1&gt;
      &lt;form onSubmit={handleSubmit}&gt;
        &lt;input
          type="text"
          name="title"
          value={title}
          onChange={(e) =&gt; setTitle(e.target.value)}
          placeholder="book title"
        /&gt;
        &lt;br /&gt;
        &lt;input
          type="text"
          name="author"
          value={author}
          onChange={(e) =&gt; setAuthor(e.target.value)}
          placeholder="book author"
        /&gt;
        &lt;br /&gt;
        &lt;input type="submit" /&gt;
      &lt;/form&gt;
      {books ? &lt;Books books={books} /&gt; : "Loading..."}
    &lt;/div&gt;
  );
};

export default Home;
</code></pre><p>Ahora podemos usar las funciones API del backend al usar <code>api</code> de Convex. Como puedes ver, llamamos a dos funciones de la API: puedes usar <code>useQuery</code> si vas a obtener datos y <code>useMutation</code> si quieres cambiar los datos. Ahora en este archivo, que estamos haciendo, dos operaciones que son create y read.</p><p>Obtuvimos todos los datos al usar este método:</p><pre><code class="language-typescript"> const books = useQuery(api.queries.getBooks);
</code></pre><p>El arreglo de objetos serán almacenados en la variable books.</p><p>Obtuvimos la función create del backend con esta línea de código:</p><pre><code class="language-typescript">const createBooks = useMutation(api.queries.createBooks);
</code></pre><h3 id="c-mo-usar-la-funci-n-create-en-el-ui"><strong>Cómo usar la función<strong> </strong>create<strong> </strong>en el<strong> UI</strong></strong></h3><p>Usemos la función create en el UI.</p><p>Ya que los campos input están en la etiqueta <code>form</code>, usaremos el atributo <code>onSubmit</code> para manejar el envío del formulario.</p><pre><code class="language-typescript">// En el Home.tsx

const handleSubmit = (e: React.FormEvent&lt;HTMLFormElement&gt;): void =&gt; {
    e.preventDefault();
    createBooks({ title, author })
      .then(() =&gt; {
        console.log("created");
        setTitle("");
        setAuthor("");
      })
      .catch((err) =&gt; console.log(err));
  };
</code></pre><p>Cuando haces clic en submit, dispara la función <code>handleSubmit</code>.</p><p>Usamos el <code>createBooks</code> para pasar el <code>title</code> y <code>author</code> del estado. La función del endpoint es async, por lo que podemos usar el <code>handleSubmit</code> como async o usar <code>.then</code>. Usé el método <code>.then</code> para manejar los datos asíncronos.</p><p>Puedes crear un componente separado para mostrar los datos solicitados de la base de datos. Los datos regresados están en el <strong>Home.tsx</strong>, así que pasaremos los datos al componente <strong>Book.jsx</strong> como props.</p><p>En <strong><strong>Books.tsx</strong></strong>:</p><pre><code class="language-tsx">import { useState } from "react";
import { book } from "../types/book.type";
import { useMutation } from "convex/react";
import { api } from "../../convex/_generated/api";
import { Id } from "../../convex/_generated/dataModel";
import "../styles/book.css";

export const Books = ({ books }: { books: book[] }) =&gt; {
  const [update, setUpdate] = useState(false);
  const [id, setId] = useState("");

  const deleteBooks = useMutation(api.queries.deleteBooks);
  const updateStatus = useMutation(api.queries.updateStatus);

  const handleClick = (id: string) =&gt; {
    setId(id);
    setUpdate(!update);
  };

  const handleDelete = (id: string) =&gt; {
    deleteBooks({ id: id as Id&lt;"books"&gt; })
      .then((mess) =&gt; console.log(mess))
      .catch((err) =&gt; console.log(err));
  };

  const handleUpdate = (e: React.FormEvent&lt;HTMLFormElement&gt;, id: string) =&gt; {
    e.preventDefault();
    const formdata = new FormData(e.currentTarget);
    const isCompleted: boolean =
      (formdata.get("completed") as string) === "true";
    updateStatus({ id: id as Id&lt;"books"&gt;, isCompleted })
      .then((mess) =&gt; console.log(mess))
      .catch((err) =&gt; console.log(err));
    setUpdate(false);
  };

  return (
    &lt;div&gt;
      {books.map((data: book, index: number) =&gt; {
        return (
          &lt;div
            key={data._id}
            className={`book-container ${data.isCompleted ? "completed" : "not-completed"}`}
          &gt;
            &lt;h3&gt;Book no: {index + 1}&lt;/h3&gt;
            &lt;p&gt;Book title: {data.title}&lt;/p&gt;
            &lt;p&gt;Book Author: {data.author}&lt;/p&gt;
            &lt;p&gt;
              Completed Status:{" "}
              {data.isCompleted ? "Completed" : "Not Completed"}
            &lt;/p&gt;
            &lt;button onClick={() =&gt; handleClick(data._id)}&gt;Update&lt;/button&gt;
            {id === data._id &amp;&amp; update &amp;&amp; (
              &lt;&gt;
                &lt;form onSubmit={(e) =&gt; handleUpdate(e, data._id)}&gt;
                  &lt;select name="completed"&gt;
                    &lt;option value="true"&gt;Completed&lt;/option&gt;
                    &lt;option value="false"&gt;Not Completed&lt;/option&gt;
                  &lt;/select&gt;
                  &lt;input type="submit" /&gt;
                &lt;/form&gt;
              &lt;/&gt;
            )}
            &lt;button onClick={() =&gt; handleDelete(data._id)}&gt;delete&lt;/button&gt;
          &lt;/div&gt;
        );
      })}
    &lt;/div&gt;
  );
};
</code></pre><p>En el componente <strong>Book.jsx, </strong>puedes mostrar los datos de la base de datos y manejar la funcionalidad para actualizar y eliminar los registros.</p><p>Veamos paso a paso cada una de estas características.</p><h3 id="c-mo-mostar-los-datos"><strong>Cómo mostar<strong> </strong>los<strong> Dat</strong>os</strong></h3><p>Puedes obtener los datos pasados como un prop en el componente <code>Home.tsx</code>. Si estás usando TypeScript, he definido un tipo para el objeto que es regresado de la solicitud. Puedes ignorar esto si estás usando JavaScript.</p><p>Crea <strong><strong><code>books.types.ts</code></strong></strong>:</p><pre><code class="language-typescript">export type book = {
    _id: string,
    title: string,
    author: string,
    isCompleted: boolean
}
</code></pre><p>Puedes usar la función <code>map</code> para mostrar los datos.</p><pre><code class="language-tsx">import { useState } from "react";
import { book } from "../types/book.type";
import { useMutation } from "convex/react";
import { api } from "../../convex/_generated/api";
import { Id } from "../../convex/_generated/dataModel";
import "../styles/book.css";

export const Books = ({ books }: { books: book[] }) =&gt; {
  const [update, setUpdate] = useState(false);

  return (
    &lt;div&gt;
      {books.map((data: book, index: number) =&gt; {
        return (
          &lt;div
            key={data._id}
            className={`book-container ${data.isCompleted ? "completed" : "not-completed"}`}
          &gt;
            &lt;h3&gt;Book no: {index + 1}&lt;/h3&gt;
            &lt;p&gt;Book title: {data.title}&lt;/p&gt;
            &lt;p&gt;Book Author: {data.author}&lt;/p&gt;
            &lt;p&gt;
              Completed Status:{" "}
              {data.isCompleted ? "Completed" : "Not Completed"}
            &lt;/p&gt;
            &lt;button onClick={() =&gt; handleClick(data._id)}&gt;Update&lt;/button&gt;
            {id === data._id &amp;&amp; update &amp;&amp; (
              &lt;&gt;
                &lt;form onSubmit={(e) =&gt; handleUpdate(e, data._id)}&gt;
                  &lt;select name="completed"&gt;
                    &lt;option value="true"&gt;Completed&lt;/option&gt;
                    &lt;option value="false"&gt;Not Completed&lt;/option&gt;
                  &lt;/select&gt;
                  &lt;input type="submit" /&gt;
                &lt;/form&gt;
              &lt;/&gt;
            )}
            &lt;button onClick={() =&gt; handleDelete(data._id)}&gt;delete&lt;/button&gt;
          &lt;/div&gt;
        );
      })}
    &lt;/div&gt;
  );
};
</code></pre><p>Esta es la estructura básica. Mostramos el título, autor, y estado, junto con un botón actualizar y eliminar.</p><p>Ahora, agreguemos las funcionalidades.</p><pre><code class="language-tsx">import { useState } from "react";
import { book } from "../types/book.type";
import { useMutation } from "convex/react";
import { api } from "../../convex/_generated/api";
import { Id } from "../../convex/_generated/dataModel";
import "../styles/book.css";

export const Books = ({ books }: { books: book[] }) =&gt; {
  const [update, setUpdate] = useState(false);
  const [id, setId] = useState("");

  const deleteBooks = useMutation(api.queries.deleteBooks);
  const updateStatus = useMutation(api.queries.updateStatus);

  const handleClick = (id: string) =&gt; {
    setId(id);
    setUpdate(!update);
  };

  const handleDelete = (id: string) =&gt; {
    deleteBooks({ id: id as Id&lt;"books"&gt; })
      .then((mess) =&gt; console.log(mess))
      .catch((err) =&gt; console.log(err));
  };

  const handleUpdate = (e: React.FormEvent&lt;HTMLFormElement&gt;, id: string) =&gt; {
    e.preventDefault();
    const formdata = new FormData(e.currentTarget);
    const isCompleted: boolean =
      (formdata.get("completed") as string) === "true";
    updateStatus({ id: id as Id&lt;"books"&gt;, isCompleted })
      .then((mess) =&gt; console.log(mess))
      .catch((err) =&gt; console.log(err));
    setUpdate(false);
  };

  return (
    &lt;div&gt;
      {books.map((data: book, index: number) =&gt; {
        return (
          &lt;div
            key={data._id}
            className={`book-container ${data.isCompleted ? "completed" : "not-completed"}`}
          &gt;
            &lt;h3&gt;Book no: {index + 1}&lt;/h3&gt;
            &lt;p&gt;Book title: {data.title}&lt;/p&gt;
            &lt;p&gt;Book Author: {data.author}&lt;/p&gt;
            &lt;p&gt;
              Completed Status:{" "}
              {data.isCompleted ? "Completed" : "Not Completed"}
            &lt;/p&gt;
            &lt;button onClick={() =&gt; handleClick(data._id)}&gt;Update&lt;/button&gt;
            {id === data._id &amp;&amp; update &amp;&amp; (
              &lt;&gt;
                &lt;form onSubmit={(e) =&gt; handleUpdate(e, data._id)}&gt;
                  &lt;select name="completed"&gt;
                    &lt;option value="true"&gt;Completed&lt;/option&gt;
                    &lt;option value="false"&gt;Not Completed&lt;/option&gt;
                  &lt;/select&gt;
                  &lt;input type="submit" /&gt;
                &lt;/form&gt;
              &lt;/&gt;
            )}
            &lt;button onClick={() =&gt; handleDelete(data._id)}&gt;delete&lt;/button&gt;
          &lt;/div&gt;
        );
      })}
    &lt;/div&gt;
  );
};
</code></pre><p>Este es todo el código del componente. Déjame explicarte qué hice.</p><p>Primero, necesitamos alternar la actualización, así que definimos la función <code>handleClick</code>, y le pasamos un ID del documento.</p><pre><code class="language-typescript">//handleClick
 const handleClick = (id: string) =&gt; {
    setId(id);
    setUpdate(!update);
  };
</code></pre><p>En el <code>handleClick</code> puedes actualizar el estado del ID y alternar el estado de la actualización de forma que alternará la actualización cuando se haga clic, y en otro clic, se cerrará.</p><p>Luego, tenemos <code>handleUpdate</code>. Necesitamos el ID del documento para actualizar los datos, así que pasamos el objeto evento así también como el ID del documento. Para obtener la entrada, podemos usar <code>FormData</code>.</p><pre><code class="language-typescript">const updateStatus = useMutation(api.queries.updateStatus);

const handleUpdate = (e: React.FormEvent&lt;HTMLFormElement&gt;, id: string) =&gt; {
    e.preventDefault();
    const formdata = new FormData(e.currentTarget);
    const isCompleted: boolean =
      (formdata.get("completed") as string) === "true";
    updateStatus({ id: id as Id&lt;"books"&gt;, isCompleted })
      .then((mess) =&gt; console.log(mess))
      .catch((err) =&gt; console.log(err));
    setUpdate(false);
  };
</code></pre><p>Necesitamos usar el <code>useMutation</code> para obtener la función <code>updateStatus</code>. Pasa el ID y el estado completado a la función, y maneja la parte asíncrona usando <code>.then</code>.</p><p>Para la función delete, el ID del documento es suficiente. Como el anterior, llama la función delete usando el <code>useMutation</code> y pásale el ID.</p><p>Luego pasa el ID del documento y maneja la promesa.</p><pre><code class="language-typescript">const deleteBooks = useMutation(api.queries.deleteBooks);

const handleDelete = (id: string) =&gt; {
    deleteBooks({ id: id as Id&lt;"books"&gt; })
      .then((mess) =&gt; console.log(mess))
      .catch((err) =&gt; console.log(err));
 };
</code></pre><!--kg-card-begin: html--><h2 id="estilos">Estilos</h2><!--kg-card-end: html--><p>Finalmente, lo que queda es agregar algo de estilo. Agregué algunos estilos básicos. Si el libro no ha sido completado, estará en rojo, y si el libro se ha completado, estará en verde.</p><p>Aquí la captura de pantalla:</p><figure class="kg-card kg-image-card"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1729428111374/1d1a69ef-5d35-4410-91f4-d8cf4817991d.png" class="kg-image" alt="final output" width="851" height="601" loading="lazy"></figure><p>¡¡Esto es todo chicos!!</p><p>Puedes visitar mi repositorio para ver todo el código: <a href="https://github.com/sanjayr-12/convex-crud">convex-curd</a></p><!--kg-card-begin: html--><h2 id="resumen">Resumen</h2><!--kg-card-end: html--><p>En este artículo, implementamos las operaciones CRUD (Crear, Leer, Actualizar y Eliminar) al construir una aplicación de colecciones de libros. Comenzamos configurando Convex y React, y escribir la lógica de CRUD.</p><p>Este tutorial cubrió tanto el frontend como el backend, demostrando cómo construir una aplicación serverless.</p><p>Puedes encontrar todo el código aquí: <a href="https://github.com/sanjayr-12/convex-crud">convex-curd</a></p><p>Si hay algún error o cualquier duda, contáctame en <a href="https://www.linkedin.com/in/sanjay-r-ab6064294/">LinkedIn</a>, <a href="https://www.instagram.com/_sanjayxr_12_/">Instagram</a>.</p><p>¡Gracias por leer!</p> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Operaciones CRUD  – ¿Qué es CRUD? ]]>
                </title>
                <description>
                    <![CDATA[  CRUD no es una palabra. Es más bien una abreviación en inglés, que significa: - Create - crear - Read - leer - Update - actualizar - Delete - eliminar o destruir En este artículo te mostraré lo que significa  CRUD y cada una de sus siglas, también te ]]>
                </description>
                <link>https://www.freecodecamp.org/espanol/news/operaciones-crud-que-es-crud/</link>
                <guid isPermaLink="false">64c54dce73ccf107b75200f3</guid>
                
                    <category>
                        <![CDATA[ crud ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Desarrollo Backend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ full stack ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Franciscomelov ]]>
                </dc:creator>
                <pubDate>Fri, 09 Feb 2024 12:38:33 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/espanol/news/content/images/2024/02/crud.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p> CRUD no es una palabra. Es más bien una abreviación en inglés, que significa:</p><p>- Create - crear<br>- Read - leer<br>- Update - actualizar<br>- Delete - eliminar o destruir</p><p>En este artículo te mostraré lo que significa &nbsp;CRUD y cada una de sus siglas, también te enseñaré cómo funcionan las operaciones CRUD de crear, leer, actualizar y eliminar en el mundo real.</p><h2 id="-ndice"><strong>Índice</strong></h2><ul><li>¿Qué es CRUD?</li><li>¿Qué es la operación <code>CREATE</code> (Crear) y cómo funciona?</li><li>¿Qué es la operación <code>READ</code> (Leer) y cómo funciona?</li><li>¿Qué es la operación<code>UPDATE</code> (Actualizar) y cómo funciona?</li><li>¿Qué es la operación <code>DELETE</code> (Eliminar) y cómo funciona?</li><li>Conclusión</li></ul><h2 id="-qu-es-crud"><strong>¿Qué es CRUD?</strong></h2><p>CRUD se refiere a las cuatro operaciones básicas que una aplicación debería poder hacer- "Create - Crear", "Read - Leer", "Update - Actualizar" y "Delete - eliminar"</p><p>En una aplicación, el usuario debe de ser capaz de crear datos, poder leerlos y tener acceso a ellos desde la interfaz gráfica, actualizar o editar los datos y ser capaz de eliminarlos.</p><p>Las aplicaciones CRUD completas, consisten de 3 partes: una API (o servidor), una base de datos y una interfaz de usuario (IU/UI - user interface).</p><p>La API contiene código y métodos, la base de datos almacena y ayuda al usuario a extraer información, mientras que la interfaz de usuario ayuda a los usuarios a interactuar con la aplicación.</p><p>Puedes hacer una aplicación CRUD con cualquier lenguaje de programación existente. La aplicación no tiene que ser full-stack puedes hacer aplicaciones CRUD solo con JavaScript en el lado del cliente.</p><p>De hecho, la aplicación con la que te enseñaré cómo hacer operaciones CRUD - crear, leer, actualizar y eliminar, funciona solo con JavaScript del lado del cliente.</p><p>Cada letra en CRUD tiene un método de petición HTTP (HTTP request) correspondiente.</p><p>*Recuerda que es normal que en programación las instrucciones sean en inglés, ya que en este idioma están hechos la mayoría de los lenguajes de programación.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/01/image-2.png" class="kg-image" alt="image-2" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/01/image-2.png 600w, https://www.freecodecamp.org/espanol/news/content/images/2024/01/image-2.png 635w" width="635" height="211" loading="lazy"></figure><h2 id="-cu-l-es-la-operaci-n-create-y-c-mo-funciona"><strong>¿Cuál es la operación <code>CREATE</code> y cómo funciona?</strong></h2><p>La operación CREATE (crear) como su nombre lo dice, crea un dato, este dato puede ser un usuario, información del usuario, una publicación o una tarea.</p><p>Como mencioné antes, la instrucción HTTP que ejecuta la operación <code>CREATE</code>es el método POST.</p><p>CREATE es el equivalente a <code>INSERT</code> (INSERTAR) en una base de datos SQL. En una base de datos NoSQL como MongoDB, se utiliza la instrucción <code>insert()</code>.</p><p>En la interfaz de usuario, que se muestra el siguiente GIF, se muestra cómo funciona la operación <code>CREATE</code>.</p><p>Primero se escribe el dato en la caja de texto y al dar clic en <code>Submit</code>, se crea o agrega un dato en nuestra aplicación.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2022/06/create-op.gif" class="kg-image" alt="create-op" width="600" height="400" loading="lazy"></figure><h2 id="-qu-es-la-operaci-n-read-y-c-mo-funciona"><strong>¿Qué es la operación <code>READ</code> y cómo funciona?</strong></h2><p>La operación <code>READ</code> (leer) nos permite tener acceso, poder ver o leer los datos o información desde la interfaz gráfica, que pueden ser desde información de los usuarios, publicaciones de redes sociales, etc.</p><p>Se puede acceder a estos datos inmediatamente después de introducirlos en la aplicación o buscarlos después. Una caja de búsqueda se implementa para permitir a los usuarios filtrar los datos que no necesitan.</p><p>El método HTTP GET es el encargado de implementar la operación <code>READ</code>.</p><p>READ es el equivalente a <code>SELECT</code> (seleccionar) en una base de datos SQL. En una base de datos NoSQL como MongoDB, para leer se utiliza el método <code>find()</code> o <code>findById()</code></p><p>En el siguiente ejemplo, en la sección "Entries" se puede ver cómo se leen o se muestran los datos previamente ingresados en la aplicación.</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2022/06/read-operation.png" class="kg-image" alt="read-operation" width="600" height="400" loading="lazy"></figure><h2 id="-qu-es-la-operaci-n-update-y-c-mo-funciona"><strong>¿Qué es la operación <code>UPDATE</code> y cómo funciona?</strong></h2><p>La operación <code>UPDATE</code> (actualizar) nos permite modificar datos existentes o editar los datos de la aplicación.</p><p>A diferencia de <code>READ</code>, la operación <code>UPDATE</code> modifica los datos existentes, haciendo cambios a estos.</p><p>PUT y PATCH &nbsp;son los protocolos HTTP con los que se puede implementar la operación <code>UPDATE</code>, dependiendo de lo que necesites.</p><p>Utilizarás <code>PUT</code> cuando quieras modificar todo un dato, y PATCH si solo quieres modificar una parte de este.</p><p>En una base de datos SQL, se utiliza <code>UPDATE</code> para actualizar un dato, en una base de datos NoSQL como MongoDB, puedes implementar una actualización con el método <code>findByIdAndUpdate()</code>.</p><p>En el siguiente ejemplo nos muestran cómo funciona la operación <code>UPDATE</code>, dando clic en el botón "Update" podemos modificar un dato de la lista.<br></p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2022/06/update-op.gif" class="kg-image" alt="update-op" width="600" height="400" loading="lazy"></figure><h2 id="-qu-es-la-operaci-n-delete-y-c-mo-funciona"><strong>¿Qué es la operación <code>DELETE</code> y cómo funciona?</strong></h2><p><code>DELETE</code> (eliminar) nos permite eliminar o deshacernos de un dato de la interfaz de usuario y de la base de datos.</p><p><code>DELETE</code> es el protocolo HTTP que nos permita implementar la operación <code>DELETE</code>.</p><p>En una base de datos SQL, <code>DELETE</code> se utiliza para eliminar un dato. En una base de datos NoSql como MongoDB, puedes implementar una función de eliminar con el método <code>findByIdAndDelete()</code>.</p><p>En el siguiente ejemplo podemos ver cómo se elimina cada elemento de la lista al dar clic en el botón "Delete"</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/news/content/images/2022/06/delete-op.gif" class="kg-image" alt="delete-op" width="600" height="400" loading="lazy"></figure><h2 id="conclusi-n"><strong>Conclusión</strong></h2><p>Este artículo te mostró lo que significa CRUD, y qué hace cada una de sus funciones en una aplicación CRUD.</p><p>Puedes pensar en CRUD de la siguiente forma:</p><figure class="kg-card kg-image-card"><img src="https://www.freecodecamp.org/espanol/news/content/images/2024/01/image-2.png" class="kg-image" alt="image-2" srcset="https://www.freecodecamp.org/espanol/news/content/images/size/w600/2024/01/image-2.png 600w, https://www.freecodecamp.org/espanol/news/content/images/2024/01/image-2.png 635w" width="635" height="211" loading="lazy"></figure><ul><li>Puedes "crear" una cuenta y añadir tu información en una red social - <code>CREATE</code></li><li>Puedes acceder a la información que ingresaste y otras personas te pueden buscar – <code>READ</code></li><li>Al obtener un trabajo en Google hay que cambiar/actualizar tu información de trabajo – <code>UPDATE</code></li><li>Si te cansas de la toxicidad de las redes sociales y eliminas tu cuenta - <code>DELETE</code></li></ul><p>Para aprender a hacer tu propia aplicación CRUD - puedes ver <a href="https://www.freecodecamp.org/news/learn-crud-operations-in-javascript-by-building-todo-app/">este tutorial</a> de Joy Shaheb en FreeCodeCamp.</p><p>!No pares de programar¡👋</p> ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
