برنامه نویسی

جهش های ساده با TanStack Query و Next.js

جهش با TanStack Query همیشه کمی ترسناک بوده است – حداقل تا زمانی که تصمیم گرفتم آنها را امتحان کنم. پس از استفاده زیاد از آنها دیگر راه برگشتی وجود ندارد.

بنابراین امروز می‌خواهم به شما نشان دهم که چگونه می‌توانید اولین جهش خود را بنویسید و شما را از طریق مشکلات کوچکی که ممکن است در این راه رخ دهد راهنمایی کنید.

کد این مثال در این مخزن است که حاوی مجموعه ای از مفاهیمی که من نوشتم، اثبات TanStack است. جهشی که ما در مورد آن صحبت می کنیم اینجاست.

جهش برای چیست؟

جهش‌ها طوری طراحی شده‌اند که برای هر چیزی که عملیات GET نیست استفاده شود، بنابراین می‌توانیم از آنها برای ارسال، قرار دادن و/یا حذف داده‌ها استفاده کنیم. برای ساده کردن این کار، من یک پایگاه داده ساختگی با json-server و چند todo-item راه اندازی کردم که شخصیت های محبوب ما از دنیای Rick and Morty باید در طول قسمت ها انجام دهند. اجرا را فراموش نکنید npm run json-server برای راه اندازی آن

ما می خواهیم نتیجه چیزی شبیه به این باشد:

لیست کارهای نهایی ریک و مورتی

یک کار جدید ایجاد کنید

بیایید ابتدا با نوشتن تابع برای POST واقعی شروع کنیم. این باید خیلی سرراست باشد.

async function createTodo(todo) {
  const response = await fetch("http://localhost:8000/todos", {
    method: "POST",
    headers: {
      "content-type": "application/json",
    },
    body: JSON.stringify({
      id: nanoid(),
      user: todo.user,
      task: todo.task,
      done: false,
    }),
  });

  const result = await response.json();

  if (!response.ok) {
    throw new Error(result.message);
  }
  return result;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این فقط از fetch برای ارسال درخواست پست با TODO به عنوان آرگومان استفاده می کند و نتیجه را برمی گرداند. اگر مشکلی پیش بیاید، خطا رخ می دهد.

اکنون می‌توانیم فرمی ایجاد کنیم تا کارهای خود را در آن بنویسیم:

     <form onSubmit={onFormSubmit} className="grid grid-cols-1 gap-4">
        <div className="flex gap-4 items-end">
          <label htmlFor="user" className="text-xl font-bold">
            User:
          </label>
          <input
            type="text"
            className="text-black flex-1"
            name="user"
            id="user"
            onChange={changeTodo}
            value={todo.user}
          />
        </div>
        <div className="flex gap-4 items-end">
          <label htmlFor="task" className="text-xl font-bold">
            Task:
          </label>
          <input
            type="text"
            className="text-black flex-1"
            name="task"
            id="task"
            onChange={changeTodo}
            value={todo.task}
          />
        </div>
        <button type="submit" className="justify-self-end">
          create todo
        </button>
      </form>
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

البته، این به برخی حالت ها و توابع نیز نیاز دارد که تغییر حالت را مدیریت می کند:

const [todo, setTodo] = useState({ user: "", task: "" });
  function changeTodo(e) {
    const newObject = {};
    newObject[e.target.name] = e.target.value;
    setTodo({ ...todo, ...newObject });
  }
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون که این تنظیم شده است، بیایید به خود جهش نگاه کنیم. قلاب useMutation تنها یک آرگومان اجباری دارد، که تابعی است که به API ما ارسال می‌کند و باید یک Promise را برگرداند. در مورد ما، این خواهد بود:

const createTodoMutation = useMutation(createTodo)
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون، تنها کاری که باید انجام دهید این است که هر بار که یک todo ارسال می‌شود، به فرم بگویید که داده‌ها را جهش کند. برای مثال می توانید این کار را در کنترل کننده onSubmit انجام دهید:

  function onFormSubmit(e) {
    e.preventDefault();
    createTodoMutation.mutate(todo);
  }
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

پس بیایید خلاصه کنیم:

  1. کاربر یک todo را در فیلد تایپ می کند و روی ارسال کلیک می کند.
  2. در کنترل کننده ارسال، از پیش فرض جلوگیری می شود و تابع mutate برای قلاب useMutation فراخوانی می شود. به عنوان یک آرگومان، داده هایی را که می خواهید به تابع createTodo منتقل کنید، می گیرد.
  3. تابع createTodo تماس API را انجام می دهد و اکنون باید ببینید که سرور json درخواست POST را در گزارش های خود نشان می دهد. همچنین، کار جدید شما باید در داخل فایل db.json قابل مشاهده باشد.

لیست همه کارها

همه اینها خوب و خوب است، اما ما هنوز نمی توانیم کارهای خود را در صفحه ببینیم، فرم فقط به ما اجازه می دهد موارد جدید را ارسال کنیم. پس بیایید چند کد سریع برای تجسم کارهایمان اضافه کنیم.

ما به یک تابع برای واکشی از API خود نیاز داریم:

async function fetchTodos() {
  return fetch("http://localhost:8000/todos").then((res) => res.json());
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در کامپوننت خود، می توانیم از قلاب useQuery برای به دست آوردن کارهای خود استفاده کنیم:

const todos = useQuery(["todos"], fetchTodos);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

برای اینکه کد خود را پاک‌تر کنم، یک جزء todo اضافی ایجاد کردم:

function Todo({ todo }) {
  return (
    <div className="bg-white text-black rounded-lg grid grid-cols-[auto_1fr_auto] items-center gap-4 py-2 px-4">
      <input
        type="checkbox"
        checked={todo.done}
        onChange={(e) => changeTodoStatus(e, todo.id)}
      />
      <p>{todo.task}</p>
      <Image
        src={todo.user}
        alt="profile picture"
        className="rounded-full"
        height={60}
        with={60}
      ></Image>
    </div>
  );
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

و اکنون فقط باید کارهای خود را تکرار کنیم و آنها را به این صورت نشان دهیم:

{todos.isLoading ? <span className="loader"></span> : null}
      <div className="grid grid-cols-2 gap-4 pt-8">
{todos.isSuccess
          ? todos.data.map((todo) => <Todo todo={todo} key={todo.id}></Todo>)
          : null}
      </div>
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کار ما تمام شد، درست است؟

اگر این را امتحان کردید، انتظار دارید که کار جدید پس از ایجاد آن به طور خودکار ظاهر شود، اما این اتفاق نمی‌افتد. دلیلش این است که ما هرگز به قلاب useQuery خود نگفتیم که کوئری خود را به روز کند. از آنجایی که پایگاه داده تغییر کرده است، ما باید راهی برای ارتباط قلاب ها با یکدیگر پیدا کنیم: آیا قلاب useMutation نمی تواند به قلاب useQuery بگوید که باید کش را به روز کند؟

بله می تواند و این کاری است که ما می خواهیم انجام دهیم. بیایید استفاده قبلی خود را برای موارد زیر تغییر دهیم:

const queryClient = useQueryClient();
const changeTodoMutation = useMutation(updateTodo, {
    onSuccess: () => queryClient.invalidateQueries({ queryKeys: ["todos"] }),
  });
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ما تصمیم داریم پرس و جوهایی را که حاوی queryKey “todos” هستند، بی اعتبار کنیم، که روشی است برای درخواست از TanStack query برای به روز رسانی داده های مربوطه. همچنین می‌توانیم کاری مانند «queryClient.refetch({queryKeys: [“todos”]})، که ضروری است، اما راه توصیه شده فقط این است که حافظه پنهان را باطل کنید و به کتابخانه اجازه دهید بقیه را مدیریت کند.

نتیجه

این یک مثال بسیار ابتدایی است که من زیاد استفاده کرده ام: پست کردن چیزی و بازیابی فوری آن برای به روز نگه داشتن رابط کاربری. شاید قبلاً مشکوک باشید که چگونه یک کار واحد را به روز کنید؟ خودتان آن را امتحان کنید و سپس راه حل موجود در مخزن را بررسی کنید.
_

عکس کارلوس موزا در Unsplash

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا