इस पोस्ट में, हम रीमिक्स और सर्वरलेस रेडिस (अपस्टैश) का उपयोग करके एक साधारण TODO ऐप लिखेंगे।
<ब्लॉकक्वॉट>रीमिक्स एक पूर्ण स्टैक वेब ढांचा है जो आपको उपयोगकर्ता इंटरफ़ेस पर ध्यान केंद्रित करने और तेज़, स्लीक और लचीला उपयोगकर्ता अनुभव प्रदान करने के लिए वेब मूलभूत सिद्धांतों के माध्यम से वापस काम करने देता है।
रीमिक्स प्रोजेक्ट बनाएं
निम्न आदेश चलाएँ:
npx create-remix@latest
परियोजना तैयार है। अब निर्भरताएँ स्थापित करते हैं और चलाते हैं:
npm install
npm run dev
उपयोगकर्ता इंटरफ़ेस
हम टूडू आइटम के लिए एक सरल फॉर्म और एक सूची तैयार करेंगे:
// 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 () => {
// example data
return [
{ id: 1, text: "Task 1", status: false },
{ id: 2, text: "Task 2", status: true },
];
};
export const action: ActionFunction = async ({ request }) => {
// this will be used for create, update and delete operations
};
export default function Index() {
// for loading and form actions
const transition = useTransition();
// to use the loaded data in the page
const todos: Todo[] = useLoaderData();
const isCreating = transition.submission?.method === "POST";
const isAdding = transition.state === "submitting" && isCreating;
// split the finished and unfinished items
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(() => {
// reset the form after the create
if (isAdding) return;
formRef.current?.reset();
inputRef.current?.focus();
}, [isAdding]);
return (
<main className="container">
{/* crete form */}
<Form ref={formRef} method="post">
<input
ref={inputRef}
type="text"
name="text"
autoComplete="off"
className="input"
placeholder="What needs to be done?"
disabled={isCreating}
/>
</Form>
{/* uncompleted tasks */}
<div className="todos">
{uncheckedTodos.map((todo) => (
<TodoItem key={todo.id} {...todo} />
))}
</div>
{/* completed tasks */}
{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">
{/* this hidden input will keep the data for our todo item */}
<input
type="hidden"
name="todo"
defaultValue={JSON.stringify({ id, text, status })}
/>
{/* Remix forms are just like traditional web forms. I like this. */}
<button type="submit" className="checkbox">
{status && "✓"}
</button>
</Form>
<span className="text">{text}</span>
</div>
);
}
अब हमारी CSS फ़ाइल जोड़ने का समय आ गया है। एक सीएसएस फ़ाइल बनाएं app/styles/app.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
. के अंतर्गत सीएसएस आयात करें :
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
:::noteUpstash Redis API के साथ संगत है, इसलिए आप किसी भी Redis क्लाइंट का उपयोग कर सकते हैं लेकिन आपको नीचे दिए गए कोड को बदलने की आवश्यकता है।:::
हम केवल फ़ॉर्म सबमिट करके नए TODO आइटम जोड़ सकते हैं। हम नए आइटम को रेडिस हैश में सहेजते हैं।
<ब्लॉकक्वॉट>
कॉपी/पेस्ट करें UPSTASH_REDIS_REST_URL
वे UPSTASH_REDIS_REST_TOKEN
Upstash कंसोल से।
// 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,
},
});
}
// to fetch the list after each operation
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,
}));
// sort by date (id=timestamp)
return todos.sort((a, b) => parseInt(b.id) - parseInt(a.id));
};
हमारे पास 'बनाएं' और 'सूची' कार्यक्षमता है। अब हम उस हिस्से को लागू करेंगे जहां उपयोगकर्ता टूडू आइटम को हो गया के रूप में चिह्नित कर सकता है।
// app/routes/index.tsx
export const action: ActionFunction = async ({ request }) => {
const form = await request.formData();
// create
if (request.method === "POST") {
// ...
}
// update
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("/");
};
अब सब कुछ तैयार है! मैं उसी TODO एप्लिकेशन को Next.js और SvelteKit के साथ लागू करने की योजना बना रहा हूं। फिर मैं इन ढांचे में अपने अनुभव की तुलना करूंगा।
बने रहें और हमें ट्विटर और डिस्कॉर्ड पर फॉलो करें।
प्रोजेक्ट सोर्स कोड
https://github.com/upstash/redis-examples/tree/master/remix-todo-app-with-redis
प्रोजेक्ट डेमो पेज
https://remix-todo-app-with-redis.vercel.app/