কম্পিউটার

রেডিসের সাথে TODO অ্যাপ রিমিক্স করুন

এই পোস্টে, আমরা Remix এবং Serverless Redis (Upstash) ব্যবহার করে একটি সাধারণ TODO অ্যাপ লিখব।

রিমিক্স হল একটি সম্পূর্ণ স্ট্যাক ওয়েব ফ্রেমওয়ার্ক যা আপনাকে ব্যবহারকারীর ইন্টারফেসের উপর ফোকাস করতে এবং দ্রুত, চটকদার এবং স্থিতিস্থাপক ব্যবহারকারীর অভিজ্ঞতা প্রদানের জন্য ওয়েব মৌলিক বিষয়গুলির মাধ্যমে আবার কাজ করতে দেয়৷

রিমিক্স প্রকল্প তৈরি করুন

নিচের কমান্ডটি চালান:

npx create-remix@latest

রেডিসের সাথে TODO অ্যাপ রিমিক্স করুন

প্রকল্প প্রস্তুত. এখন নির্ভরতা ইনস্টল করুন এবং রান করুন:

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 () => {
  // 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 ফাইল যোগ করার সময়। একটি 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 এর অধীনে 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() {
  // ...
}

এখন আপনার দেখতে হবে:

রেডিসের সাথে TODO অ্যাপ রিমিক্স করুন

ডাটাবেস প্রস্তুত করুন

আমরা আমাদের ডেটা 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("/");
};

এখন সবকিছু প্রস্তুত! আমি Next.js এবং SvelteKit এর সাথে একই TODO অ্যাপ্লিকেশন বাস্তবায়ন করার পরিকল্পনা করছি। তারপর আমি এই ফ্রেমওয়ার্কগুলিতে আমার অভিজ্ঞতা তুলনা করব।

সাথে থাকুন এবং Twitter এবং Discord-এ আমাদের অনুসরণ করুন৷

প্রজেক্ট সোর্স কোড

https://github.com/upstash/redis-examples/tree/master/remix-todo-app-with-redis

প্রকল্প ডেমো পৃষ্ঠা

https://remix-todo-app-with-redis.vercel.app/


  1. ফ্লটার, সার্ভারলেস ফ্রেমওয়ার্ক এবং আপস্ট্যাশ (REDIS) সহ ফুলস্ট্যাক সার্ভারলেস অ্যাপ - পার্ট 1

  2. এজ ক্যাশিং সহ 5 ms গ্লোবাল রেডিস লেটেন্সি

  3. ক্লাউডফ্লেয়ার কর্মীদের সাথে রেডিস @ এজ

  4. উদাহরণ সহ Redis GEORADIUSBYMEMBER কমান্ড - Redis টিউটোরিয়াল