با این برنامه کلاسیک اصول React و مدیریت حالت را درک کنید.
هنگام مدیریت حالت های پیچیده در برنامه Next، همه چیز می تواند به سرعت مشکل شود. قلابهای سنتی مانند استفاده از کمکهای دولتی با مدیریت دولتی هستند، اما مشکل حفاری پایه را نشان میدهند. حفاری سرپایی به معنای انتقال داده ها یا عملکردها از طریق چندین جزء است.
یک رویکرد بهتر این است که منطق مدیریت حالت خود را از مؤلفه ها جدا کنید و این حالت ها را از هر جایی در برنامه خود به روز کنید. ما شما را با نحوه استفاده از Context API همراه با ساختن یک برنامه ساده فهرست کارها آشنا خواهیم کرد.
قبل از اینکه فهرست کارهای خود را شروع کنید
قبل از اینکه بتوانید برنامه لیست کارها را بسازید، به موارد زیر نیاز دارید:
- دانش اولیه اپراتورهای جاوا اسکریپت مدرن و React’s useState hook.
- درک چگونگی تخریب آرایه ها و اشیاء در جاوا اسکریپت.
- Node نسخه 16.8 یا جدیدتر نصب شده روی دستگاه محلی شما و آشنایی با مدیران بسته مانند npm یا yarn.
برای مرجع و کاوش بیشتر می توانید پروژه تمام شده را در GitHub بیابید.
درک وضعیت برنامه و مدیریت
Application State به وضعیت فعلی یک برنامه کاربردی در یک نقطه زمانی معین اشاره دارد. این شامل اطلاعاتی است که برنامه می داند و مدیریت می کند، مانند ورودی کاربر و داده های واکشی شده از پایگاه داده یا یک API (رابط برنامه نویسی برنامه).
برای درک وضعیت برنامه، حالت های ممکن یک برنامه شمارنده ساده را در نظر بگیرید. آنها عبارتند از:
- حالت پیش فرض زمانی که شمارنده روی صفر باشد.
- حالت افزایش یافته زمانی که شمارنده یک عدد افزایش می یابد.
- یک حالت کاهش یافته زمانی که شمارنده یک کاهش می یابد.
- حالت ریست زمانی که شمارنده به حالت پیش فرض خود برمی گردد.
یک کامپوننت React می تواند در تغییرات حالت مشترک شود. هنگامی که یک کاربر با چنین مؤلفه ای تعامل می کند، اقدامات او – مانند کلیک روی دکمه – می تواند به روز رسانی های وضعیت را مدیریت کند.
این قطعه یک برنامه پیشخوان ساده را در حالت پیشفرض خود نشان میدهد که وضعیت را بر اساس اقدامات کلیک مدیریت میکند:
const [counter, setCounter] = useState(0);
return (
<main>
<h1>{counter}</h1>
<button onClick={() => setCounter(counter + 1)}>increase</button>
<button onClick={() => setCounter(counter - 1)}>decrease</button>
<button onClick={() => setCounter(0)}>reset</button>
</main>
);
راه اندازی و نصب
مخزن پروژه شامل دو شاخه است: شروع و زمینه. می توانید از شاخه شروع به عنوان پایه برای ساخت پروژه یا از شاخه زمینه برای پیش نمایش نسخه آزمایشی نهایی استفاده کنید.
شبیه سازی برنامه Starter
برنامه شروع کننده رابط کاربری مورد نیاز برای برنامه نهایی را فراهم می کند، بنابراین می توانید روی اجرای منطق اصلی تمرکز کنید. یک ترمینال را باز کنید و دستور زیر را برای کلون کردن شاخه شروع مخزن به ماشین محلی خود اجرا کنید:
git clone -b starter https://github.com/makeuseofcode/Next.js-CRUD-todo-app.git
دستور زیر را در دایرکتوری پروژه اجرا کنید تا وابستگی ها را نصب کرده و سرور توسعه خود را راه اندازی کنید:
yarn && yarn dev
یا:
npm i && npm run dev
اگر همه چیز خوب پیش رفت، رابط کاربری باید در مرورگر شما نمایش داده شود:
پیاده سازی منطق
Context API راهی برای مدیریت و به اشتراک گذاری داده های وضعیت در بین اجزاء بدون نیاز به حفاری پایه دستی ارائه می دهد.
مرحله 1: ایجاد و صادرات زمینه
یک پوشه src/app/context برای ذخیره فایل متنی ایجاد کنید و فهرست پروژه را به خوبی سازماندهی کنید. در این پوشه، یک فایل todo.context.jsx ایجاد کنید که شامل تمام منطق زمینه برنامه باشد.
تابع createContext را از کتابخانه react وارد کنید و آن را فراخوانی کنید و نتیجه را در یک متغیر ذخیره کنید:
import { createContext} from "react";
const TodoContext = createContext();
در مرحله بعد، یک قلاب useTodoContext سفارشی ایجاد کنید که TodoContext را به شکل قابل استفاده آن برمی گرداند.
export const useTodoContext = () => useContext(TodoContext);
مرحله 2: ایجاد و مدیریت ایالات
برای انجام اقدامات CRUD (ایجاد، خواندن، بهروزرسانی، حذف) برنامه، باید حالتها را ایجاد کرده و با مولفه Provider مدیریت کنید.
const TodoContextProvider = ({ children }) => {
const [task, setTask] = useState("");
const [tasks, setTasks] = useState([]);
return <TodoContext.Provider value={{}}>{children}</TodoContext.Provider>;
};
export default TodoContextProvider;
درست قبل از دستور بازگشت، یک تابع handleTodoInput ایجاد کنید که وقتی کاربر یک to-do را تایپ می کند، اجرا می شود. سپس این تابع وضعیت وظیفه را به روز می کند.
const handleTodoInput = (input) => setTask(input);
یک تابع createTask اضافه کنید که وقتی کاربر یک کار را ارسال می کند اجرا می شود. این تابع وضعیت وظایف را به روز می کند و به کار جدید یک شناسه تصادفی اختصاص می دهد.
const createTask = (e) => {
e.preventDefault();
setTasks([
{
id: Math.trunc(Math.random() * 1000 + 1),
task,
},
...tasks,
]);
};
یک تابع updateTask ایجاد کنید که از طریق لیست وظایف نقشه برداری می کند و وظیفه ای را که شناسه آن با شناسه کار کلیک شده مطابقت دارد، به روز می کند.
const updateTask = (id, updateText) =>
setTasks(tasks.map((t) => (t.id === id ? { ...t, task: updateText } : t)));
یک تابع deleteTask ایجاد کنید که لیست وظایف را به روز می کند تا شامل تمام کارهایی باشد که شناسه آنها با پارامتر داده شده مطابقت ندارد.
const deleteTask = (id) => setTasks(tasks.filter((t) => t.id !== id));
مرحله 3: ایالات و هندلرها را به ارائه دهنده اضافه کنید
اکنون حالت ها را ایجاد کرده اید و کدهایی را برای مدیریت آنها نوشته اید، باید این حالت ها و توابع کنترل کننده را در دسترس ارائه دهنده قرار دهید. میتوانید با استفاده از خاصیت ارزش مولفه Provider، آنها را در قالب یک شی عرضه کنید.
return (
<TodoContext.Provider
value={{
task,
tasks,
handleTodoInput,
createTask,
updateTask,
deleteTask,
}}
>
{children}
</TodoContext.Provider>
);
مرحله 4: زمینه را در نظر بگیرید
ارائهدهندهای که ایجاد کردهاید باید مؤلفه سطح بالا را بپیچد تا زمینه در دسترس کل برنامه باشد. برای انجام این کار، src/app/page.jsx را ویرایش کنید و مؤلفه Todos را با مؤلفه TodoContextProvider بپیچید:
<TodoContextProvider>
<Todos />;
</TodoContextProvider>;
مرحله 5: از Context در Components استفاده کنید
فایل src/app/components/Todos.jsx خود را ویرایش کنید و وظایف، task، handleTodoInput و createTask را از طریق فراخوانی به تابع useTodoContext تخریب کنید.
const { task, tasks, handleTodoInput, createTask } = useTodoContext();
اکنون، عنصر فرم را برای مدیریت رویداد ارسال و تغییرات در فیلد ورودی اصلی به روز کنید:
<form onSubmit={(e) => createTask(e)}>
<input className="todo-input" type="text" placeholder="Enter a task" required value={task} onChange={(e) => handleTodoInput(e.target.value)} />
<input className="submit-todo" type="submit" value="Add task" />
</form>
مرحله 6: رندر وظایف در UI
اکنون می توانید از برنامه برای ایجاد و اضافه کردن یک کار به لیست وظایف استفاده کنید. برای بهروزرسانی نمایشگر، باید وظایف موجود را نقشه برداری کنید و آنها را در UI ارائه دهید. ابتدا یک کامپوننت src/app/components/Todo.jsx ایجاد کنید تا یک مورد تکلیف را در خود جای دهد.
در مولفه src/app/components/Todo.jsx، با فراخوانی توابع updateTask و deleteTask که در فایل src/app/context/todo.context.jsx ایجاد کردیم، یک کار را ویرایش یا حذف کنید.
import React, { useState } from "react";
import { useTodoContext } from "../context/todo.context";
const Todo = ({ task }) => {
const { updateTask, deleteTask } = useTodoContext();
// isEdit state tracks when a task is in edit mode
const [isEdit, setIsEdit] = useState(false);
return (
<table className="todo-wrapper">
<tbody>
<tr>
{isEdit ? ( <input type="text" value={task.task}
onChange={(e) => updateTask(task.id, e.target.value)} /> ) :
(<th className="task">{task.task}</th> )}
<td className="actions">
<button className="edit"
onClick={() => setIsEdit(!isEdit)}> {isEdit ? "Save" : "Edit"} </button>
<button onClick={() => deleteTask(task.id)}>Del</button>
</td>
</tr>
</tbody>
</table>
);
};
export default Todo;
برای رندر کردن مولفه src/app/components/Todo.jsx برای هر کار، به فایل src/app/components/Todos.jsx بروید و به صورت مشروط وظایف را درست بعد از برچسب بسته شدن هدر نقشه برداری کنید.
{tasks && (
<main>
{tasks.map((task, i) => ( <Todo key={i} task={task} /> ))}
</main>
)}
برنامه خود را در یک مرورگر آزمایش کنید و تأیید کنید که نتیجه مورد انتظار را ارائه می دهد.
ذخیره وظایف در فضای ذخیرهسازی محلی
در حال حاضر، بازخوانی صفحه، کارها را بازنشانی میکند و کارهایی را که ایجاد کردهاید کنار میگذارد. یکی از راه های رفع این مشکل، ذخیره وظایف در حافظه محلی مرورگر است.
Web Storage API بهبودی در ذخیره سازی کوکی ها است، با ویژگی هایی که تجربه را برای کاربران و توسعه دهندگان به طور یکسان بهبود می بخشد.