Next.js یک فریمورک مبتنی بر React برای ساخت برنامههای کاربردی، بهینهشده و مقیاسپذیر است. ما بهعنوان توسعهدهندگان React، کامپوننتها را میسازیم، state را manage و ارتباطات دادهای بین آنها را مدیریت میکنیم. سپس Next.js مطرح میشود تا بهینهسازیهای مورد نیاز را ارائه دهد.
Next.js 14 مفهوم پایدار App Router
را در اختیار ما قرار میدهد که شامل موارد زیر میباشد:
در این مقاله قصد داریم تا یک تکنیک Next.js برای data fetching به نام Server Action را مورد بحث قرار دهیم. اما قبل از آن باید با مفهوم React Server Componentها آشنا شویم.
تیم ReactJS مفهوم server componentها را در سال ۲۰۲۰ معرفی کرد. مفهوم app router
در Next.js با استفاده از طرز فکر «تفکر در server componentها» ساخته شده است.
باید به این نکته توجه کنیم که مفهوم Server Component و Server Action یکسان نیست. برای درک آسان Server Actionها، باید یک آشنایی اولیهای از Server Componentها داشته باشیم.
به عنوان یک توسعهدهنده وب، ما فرمهای HTML و form actionها را بارها پیادهسازی کردهایم. به عنوان مثال:
export default function Cart() { function addToCart(e) { // Read the Form Data // Make the API call // Change the Component state } return ( <form method="post" onSubmit={addToCart}> <label> Select your favorite brand: <select name="selectedBrand" defaultValue="apple"> <option value="apple">Apple</option> <option value="oppo">Oppo</option> <option value="samsung">Samsung</option> </select> </label> <label> Enter the Count: <input type="number" name="count" placeholder="Specify how many do you want" /> </label> <hr /> <button type="reset">Reset</button> <button type="submit">Submit</button> </form> ); }
کدی که داریم یک کامپوننت ساده React است که با استفاده از فرم، افزودن یک محصول و مقدار آن را به سبد خرید انجام میدهد. تابع addToCart
که داریم قرار است در حین افزودن موارد انتخاب شده به سبد خرید، وظایفی را انجام دهد که عبارتند از:
باید به این نکته توجه داشته باشیم که همه اینها در سمت کلاینت برنامه ما اتفاق میافتد. این بدان معنی است که کد کامپوننت به عنوان بخشی از بسته نرم افزاری در مرورگر کاربر دانلود میشود. کامپوننت یک API call از طریق شبکه برقرار میکند و منتظر میماند تا کامل شود. این انتظار میتواند بر اساس تأخیر، سرعت شبکه و غیره طولانیتر باشد.
ما میتوانیم کامپوننتهای خود را با کمک React Server Components (RSC) به سرور منتقل کرده و آنها را در پایگاه داده ذخیره کنیم تا:
این موارد با توجه به تجربه کاربری، قابلیت نگهداری و هزینه عملکرد، مزایای بسیار مهمی هستند.
وقتی کامپوننتها را با React Server Componentها به سرور منتقل میکنیم، به احتمال زیاد در پایگاه داده برنامه ما قرار میگیرند. ما هنوز هم باید دادهها را از پایگاه داده به کامپوننتهای خود fetch کنیم، اما fetch کردن دادهها بسیار سریعتر از fetch کردن از یک client component خواهد بود.
مفهوم app router
در Next.js براساس «تفکر در server componentها» ساخته شده است. همه کامپوننتها بهطور پیشفرض، server component هستند و اگر میخواهیم یک client component بنویسیم، باید آنها را به صراحت با استفاده از دستورالعمل use Client
علامتگذاری کنیم.
این بدان معنی است که یک سلسله مراتب کامپوننت در Next.js میتواند server componentها و client componentها را با هم ترکیب کند. ما میتوانیم تا حد امکان از server componentها، و هر جا که نیاز به تعامل با کاربر یا مدیریت event داشته باشیم از client componentها استفاده کنیم.
Next.js تکنیکها و الگوهای fetching دادهها را برای توسعهدهندگان ارائه میدهد که یکی از این تکنیکها، استفاده از server action است.
server actionها بر روی React Actions ساخته شدهاند که میتوانیم آنها را در server componentها تعریف کرده و یا از client componentها فراخوانی کنیم. به طور کلی، server actionها توابع async جاوااسکریپت هستند که توسط تعاملات کاربر روی کلاینت، بر روی سرور اجرا میشوند.
async function addItemToCart(data) { 'use server' await addToDB(data) }
میتوانیم server actionها را با استفاده از prop action
المنت <form/>
در ReactJS فراخوانی کنیم.
<form action={addItemToCart}> ... ... </form>
همچنین، میتوانیم از prop formAction
روی المنتهایی مانند دکمه ارسال، متن ورودی و غیره در داخل یک <form/>
استفاده نماییم.
<form action={handleSubmit}> <input type="text" name="name" formAction={handleName} /> <button type="submit">Submit</button> </form>
اکنون میخواهیم کاربرد server actionها را با توجه به server componentها و client componentها بررسی کنیم.
برای استفاده از server actionها در داخل server component، ابتدا یک تابع async با دستور use server
ایجاد میکنیم. ما باید این دستور را در بالای بدنه تابع قرار دهیم.
سپس، میتوانیم server function را از prop action
المنت <form/>
فراخوانی کنیم و یا این که از prop formAction
روی المنتهایی مانند دکمه ارسال، متن ورودی و غیره در داخل المنت <form/>
استفاده نماییم.
export default function CourseComments() { async function addCommentToCourse(comment, courseId) { 'use server' await saveComment({comment, courseId}); } return( <form action={addCommentToCourse}> <button type="submit">Add Comment</button> </form> ) }
از آنجایی که سلسله مراتب کامپوننت میتواند دارای server componentها و client componentها باشد، ممکن است بخواهیم از server actionها در داخل client componentها نیز استفاده کنیم. برای آن، actionهای خود را در یک فایل جداگانه، مثلا add-comments.js
ایجاد مینماییم.
'use server' import { addCommentToCourse } from '@/data/course' export async function addComment(data, courseId) { const response = await addCommentToCourse(data, course); return response; }
باید به این نکته توجه داشته باشیم که هنوز باید از دستور use server
در بالای فایل (حتی قبل از importها) استفاده کنیم تا Next.js را در مورد فایلی که شامل server actionها است، مطلع نماییم.
اکنون کاری که باید در client component انجام دهیم این است، همانظور که قبلا دیدهایم، فقط actionها را import کرده آنها از prop action
یا prop formAction
فراخوانی میکنیم.
'use client' import { addComment } from '@/actions/add-comment'; export default function CourseComment() { return ( <form action={addComment}> <button type="submit">Add Comment</button> </form> ) }
تا این قسمت مقاله، ما در مورد دو روش فراخوانی برای فراخوانی server actionها صحبت کردیم:
action
formAction
هر دوی این روشها به المنت <form/>
مربوط میشوند. اکنون سوالی که با آن مواجه هستیم این است که چگونه میتوانیم server actionها را خارج از المنت <form/>
فراخوانی کنیم؟ برای انجام این کار، میتوانیم با استفاده از روش startTransition
ارائه شده توسط هوک useTransition
، فراخوانی سفارشی انجام دهیم.
بیایید فرض کنیم مانند قبل server action خود را در یک فایل جداگانه داریم و میخواهیم آن را از یک client component بدون المنت <form/>
فراخوانی کنیم. برای انجام آن:
'use client' import { useTransition } from 'react' import { addComment } from '@/actions/add-comment'; export default function CourseComment() { let [isPending, startTransition] = useTransition() return ( <button onClick={() => startTransition((comment, courseId) => { addComment(comment, courseId)})}> Add Comment </button> ) }
در این مقاله سعی کردیم مفهوم server action را در Next.js بررسی کنیم. همچنین مطالعه مستندات مربوط به server action در وبسایت Next.js هم میتواند بسیار مفید باشد.
دیدگاهها:
mrhajian
آبان 25, 1402 در 2:20 ق.ظ
خیلی عالی بود خسته نباشید 😍👌