परिचय
इस पोस्ट में, हम Remix और Serverless Redis (Upstash) का उपयोग करके एक सरल TODO ऐप बनाएंगे।
Remix एक फुल-स्टैक वेब फ्रेमवर्क है जो आपको यूज़र इंटरफेस पर ध्यान केंद्रित करने और वेब फंडामेंटल्स के माध्यम से तेज़, स्लिक और रेज़िलिएंट यूज़र अनुभव देने की सुविधा देता है।
Remix प्रोजेक्ट बनाएं
नीचे दिए गए कमांड को चलाएं:
npx create-remix@latest
प्रोजेक्ट तैयार है। अब निर्भरताएं इंस्टॉल करें और चलाएं:
npm install
npm run dev
यूज़र इंटरफेस
हम TODO आइटम के लिए एक सरल फॉर्म और सूची बनाएंगे:
// app/routes/index.tsx
import type { ActionFunction, LoaderFunction } from "remix";
import { Form, useLoaderData, useTransition, redirect } from "remix";
import { useEffect, useRef } from "react";
import type { Todo } from "~/components/todo-item";
import TodoItem from "~/components/todo-item";
export const loader: LoaderFunction = async () => {
// उदाहरण डेटा
return [
{ id: 1, text: "Task 1", status: false },
{ id: 2, text: "Task 2", status: true },
];
};
export const action: ActionFunction = async ({ request }) => {
// इसका उपयोग बनाएं, अपडेट और डिलीट ऑपरेशन के लिए किया जाएगा
};
export default function Index() {
// लोडिंग और फॉर्म एक्शन के लिए
const transition = useTransition();
// पेज में लोडेड डेटा उपयोग करने के लिए
const todos: Todo[] = useLoaderData();
const isCreating = transition.submission?.method === "POST";
const isAdding = transition.state === "submitting" && isCreating;
// पूर्ण और अपूर्ण आइटम अलग करें
const uncheckedTodos = todos.filter((todo) => !todo.status);
const checkedTodos = todos.filter((todo) => todo.status);
const formRef = useRef<HTMLFormElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
// बनाएं के बाद फॉर्म रीसेट करें
if (isAdding) return;
formRef.current?.reset();
inputRef.current?.focus();
}, [isAdding]);
return (
<main className="container">
{/* फॉर्म बनाएं */}
<Form ref={formRef} method="post">
<input
ref={inputRef}
type="text"
name="text"
autoComplete="off"
className="input"
placeholder="क्या करना है?"
disabled={isCreating}
/>
</Form>
{/* अपूर्ण टास्क */}
<div className="todos">
{uncheckedTodos.map((todo) => (
<TodoItem key={todo.id} {...todo} />
))}
</div>
{/* पूर्ण टास्क */}
{checkedTodos.length > 0 && (
<div className="todos todos-done">
{checkedTodos.map((todo) => (
<TodoItem key={todo.id} {...todo} />
))}
</div>
)}
</main>
);
}
यहाँ हमारा TODO कंपोनेंट है:
// app/components/todo-item.tsx
import { Form } from "remix";
export type Todo = { id: string; text: string; status: boolean };
export default function TodoItem({ id, text, status }: Todo) {
return (
<div className="todo">
<Form method="put">
{/* यह छिपा इनपुट हमारे टूडू आइटम के लिए डेटा रखेगा */}
<input
type="hidden"
name="todo"
defaultValue={JSON.stringify({ id, text, status })}
/>
{/* Remix फॉर्म पारंपरिक वेब फॉर्म की तरह हैं। मुझे यह पसंद है। */}
<button type="submit" className="checkbox">
{status && "✓"}
</button>
</Form>
<span className="text">{text}</span>
</div>
);
}
अब हमारी CSS फ़ाइल जोड़ने का समय है। app/styles/app.css में एक CSS फ़ाइल बनाएं:
:root {
--rounded: 0.25rem;
--rounded-md: 0.375rem;
--gray-50: rgb(249, 250, 251);
--gray-100: rgb(243, 244, 246);
--gray-200: rgb(229, 231, 235);
--gray-300: rgb(209, 213, 219);
--gray-400: rgb(156, 163, 175);
--gray-500: rgb(107, 114, 128);
--gray-600: rgb(75, 85, 99);
--gray-700: rgb(55, 65, 81);
--gray-800: rgb(31, 41, 55);
--gray-900: rgb(17, 24, 39);
}
*, ::before, ::after {
box-sizing: border-box;
border: 0;
padding: 0;
}
button, input, optgroup, select, textarea {
font-family: inherit;
font-size: 100%;
line-height: inherit;
color: inherit;
margin: 0;
padding: 0;
}
button {
cursor: pointer;
background-color: white;
}
html {
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: var(--gray-800);
}
.container {
padding: 8rem 1rem 0;
margin: 0 auto;
max-width: 28rem;
}
.input {
width: 100%;
padding: 0.75rem 1rem;
background-color: var(--gray-100);
border-radius: var(--rounded-md);
}
.input::placeholder { color: var(--gray-400); }
.input:disabled { color: var(--gray-600); background-color: var(--gray-200); }
.todos { margin-top: 1.5rem; }
.todos.todos-done {
background-color: var(--gray-100);
color: var(--gray-500);
border-radius: var(--rounded-md);
}
.todo {
display: flex;
align-items: center;
padding: 0.75rem;
border-radius: var(--rounded-md);
}
.todo + .todo { border-top: 1px solid var(--gray-100); }
.todo .checkbox {
display: flex;
align-items: center;
justify-content: center;
width: 1.25rem;
height: 1.25rem;
border-radius: var(--rounded);
border: 1px solid var(--gray-300);
box-shadow: 0 1px 1px 0 rgb(0 0 0 / 10%);
}
.todo .text { margin-left: 0.75rem; }
root.tsx के तहत CSS इम्पोर्ट करें:
import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration } from "remix";
import type { MetaFunction } from "remix";
import styles from "./styles/app.css";
export function links() {
return [{ rel: "stylesheet", href: styles }];
}
export const meta: MetaFunction = () => {
return { title: "Remix Todo App with Redis" };
}
export default function App() {
// ...
}
डेटाबेस तैयार करें
हम अपना डेटा Upstash Redis में रखेंगे। तो एक Upstash डेटाबेस बनाएं। हम HTTP-आधारित Upstash क्लाइंट का उपयोग करेंगे। इंस्टॉल करें:
npm install @upstash/redis
:::note Upstash Redis API के साथ संगत है, इसलिए आप किसी भी Redis क्लाइंट का उपयोग कर सकते हैं लेकिन आपको नीचे दिए गए कोड को बदलना होगा। :::
हम फॉर्म सबमिट करके नए TODO आइटम जोड़ सकते हैं। हम नए आइटम को Redis Hash में सेव करते हैं।
Upstash कंसोल से
UPSTASH_REDIS_REST_URLऔरUPSTASH_REDIS_REST_TOKENकॉपी/पेस्ट करें।
// app/routes/index.tsx
// ...
import { Redis } from "@upstash/redis";
const redis = new Redis({
url: "UPSTASH_REDIS_REST_URL",
token: "UPSTASH_REDIS_REST_TOKEN",
});
export const action: ActionFunction = async ({ request }) => {
const form = await request.formData();
if (request.method === "POST") {
const text = form.get("text");
if (!text) return redirect("/");
await redis.hset("remix-todo-example", {
[Date.now().toString()]: { text, status: false },
});
}
// प्रत्येक ऑपरेशन के बाद सूची लाने के लिए
return redirect("/");
};
अब आइटम सूचीबद्ध करें:
// app/routes/index.tsx
export const loader: LoaderFunction = async () => {
const res = await redis.hgetall<Record<string, object>>(DATABASE_KEY);
const todos = Object.entries(res ?? {}).map(([key, value]) => ({
id: key,
...value,
}));
// तारीख के अनुसार सॉर्ट करें (id=टाइमस्टैम्प)
return todos.sort((a, b) => parseInt(b.id) - parseInt(a.id));
};
हमारे पास 'बनाएं' और 'सूची' कार्यक्षमता है। अब हम वह भाग लागू करेंगे जहां उपयोगकर्ता एक TODO आइटम को पूर्ण के रूप में चिह्नित कर सकता है।
// app/routes/index.tsx
export const action: ActionFunction = async ({ request }) => {
const form = await request.formData();
// बनाएं
if (request.method === "POST") {
// ...
}
// अपडेट
if (request.method === "PUT") {
const todo = form.get("todo");
const { id, text, status } = JSON.parse(todo as string);
await redis.hset("remix-todo-example", {
[id]: { text, status: !status },
});
}
return redirect("/");
};
अब सब कुछ तैयार है! मैं Next.js और SvelteKit के साथ इसी TODO एप्लिकेशन को लागू करने की योजना बना रहा हूं। फिर मैं इन फ्रेमवर्क में अपने अनुभव की तुलना करूंगा।
जुड़े रहें और हमें ट्विटर और डिस्कॉर्ड पर फॉलो करें।
प्रोजेक्ट सोर्स कोड
https://github.com/upstash/redis-examples/tree/master/remix-todo-app-with-redis
प्रोजेक्ट डेमो पेज
https://remix-todo-app-with-redis.vercel.app/