הפריימוורק של nextJs בהחלט מפתיע ולטובה, לא סתם הוא הדיבור החם בשוק (נכון לעכשיו), לרוב ניתן למצוא הרבה פידבקים חיוביים ופחות ביקורת שזה דיי מפתיע, ובייחוד על מה שנקרא server actions. שזמין בגרסאות החדשות (Nextjs 13^).
אז מה זה server actions?
server actions הן למעשה פונקציות, אסינכרוניות, שקורות בצד שרת, וזמינות עבור רכיבי צד שרת וגם רכיבי קליינט (server and client component), בעיקר עבור data mutations (כתיבה ועריכה של מידע). ניתן לראות לרוב את השימוש בהן עבור טפסים, כידוע לform יש את המאפיין action.
כשאנחנו כותבים בצד שרת , למשל עם Nodejs אז לרוב נעבוד בMVC ובסופו של דבר הקליינט יעשה בקשות לAPI. אך עם נקסט כל העמוד מגיע מהשרת, ולכן למה לבצע בכלל קריאות לאיזה API שאפשר פשוט לבקש לעשות עבודת שרת, ולעשות את השימוש שנרצה ופשוט להחזיר את העמוד הHTML שלנו כבר עם המידע בתצוגה שנרצה או לחילופין לבצע עבודה כלשהיא כמו לכתוב לדטהבייס. למשל, בניגוד למה שראינו בפוסט הקודם על route handler . נוכל לעשות שימוש דומה רק עם server action:

אם נסתכל על מבנה התיקיות במקרה במימוש עם server actions ניתן לראות שיש קצבים בתיקיה של actions, בדוגמה פה ישנם שני קבצים , createUser וגם getAllUsers – אם כי לא אידאלי לעשות גט עם server actions כמו כן יצירת יוזר תשרת את המטרה בהתאם להנחיות של נקסט. אבל כן מימשתי גט בשביל הדוגמה.
"use server"; import { NextResponse } from "next/server"; import sqlite3 from "sqlite3"; import { open } from "sqlite"; import { revalidatePath } from "next/cache"; let db: any = null; export const createUser = async ({ name, email, password, }: { name: string; email: string; password: string; }) => { if (!db) { db = await open({ filename: "./mydb.db", driver: sqlite3.Database, }); } const createUserSQL = `INSERT INTO users (name, email, password) VALUES ('${name}', '${email}', '${password}')`; const user = db.run(createUserSQL, (err: Error | null) => { if (err) { return new Response(JSON.stringify({ message: err.message }), { status: 500, }); } }); const userData = await user; revalidatePath("/"); return NextResponse.json({ id: userData.lastID, status: 200 }); };
אז כל server action מתחיל עם use server בראשית הקובץ, ובהמשך ניתן לראות מימוש מאד דומה לפוסט הקודם של route handlers, ונוכל להשתמש בaction הזה בכל מקום שנרצה באפליקציה שלנו , כמו כן ברכיבים שהם use client:
/** * add user component */ "use client"; import { createUser } from "@/actions/craeteUser"; import React, { useState } from "react"; import style from "./CreateUserForm.module.scss"; export default function CreaterUserForm() { const [name, setName] = useState(""); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [isLoading, setIsLoading] = useState(false); const handleCreateUser = async () => { try { setIsLoading(true); await createUser({ name, email, password }); } catch (error) { console.log("error", error); } finally { setIsLoading(false); } }; return ( <div className={style.formContainer}> <form action={handleCreateUser}> <h2>Add User</h2> <div className={style.formGroup}> <input type="text" placeholder="Name" value={name} onChange={(e) => setName(e.target.value)} /> </div> <div className={style.formGroup}> <input type="email" placeholder="Email" value={email} onChange={(e) => setEmail(e.target.value)} /> </div> <div className={style.formGroup}> <input type="password" placeholder="Password" value={password} onChange={(e) => setPassword(e.target.value)} /> </div> <button type="button" className={style.primaryBtn}> Add User </button> </form> </div> ); }
אז כמו כל טופס קלאסי , שמפעיל action, והפעם מפעיל את הactions server שלנו ושומר יוזר לתפארת. דבר נוסף שהוא חשוב מאד, ונקסט טיפלו בו בעזרת revalidatePath כן שהעמוד יודע להתרנדר בהתאם לשינויי במידע שנעשה ולהביא לנו את all users לאחר שנוצר יוזר חדש, וכך להציג את הנתונים החדשים שנקלטו, (בהמשך נדבר יותר לעמוד על revalidatation). להלן סרטון של הדוגמה שנגזר ממה הקוד שמוצג בפוסט:
סיכום שיעור nextJS – server actions
אז נכון שserver actions הם הצורה הנוחה ואפילו הפופולארית יותר בזמננו, וכן אתם תראו דוגמאות ומדריכים ברשת של שימושים של כל הקריאות עם server actions ובכלל לא תראו שימושים בroute handlers. אבל חשוב לזכור שמי שתומך בפריימוורק יצר את server actions למטרה כזו שתוכלו לייצר אקשנים מרכיבי צד לקוח שהם טפסים שמפעילים action , אז עשו שימוש נכון, וקראו ממקורות אמינים ל"בסט פרקטיס" באתר של nextjs. ושקלו מה יהיה נכון לכם לממש בפרויקט שלכם. בפוסט הבא אמשיך לדבר על שימושים בצד שרת וmiddlwares בnextjs.