<טופס>
רכיב הדפדפן המובנה <form> מאפשר לך ליצור פקדים אינטראקטיביים לשליחת מידע.
<form action={search}>
<input name="query" />
<button type="submit">Search</button>
</form>הפניה
<form>
כדי ליצור פקדים אינטראקטיביים לשליחת מידע, עבד את רכיב הדפדפן המובנה <form>.
<form action={search}>
<input name="query" />
<button type="submit">Search</button>
</form>אבזרים
<form> תומך בכל הרכיב המשותף props.
action: כתובת URL או פונקציה. כאשר כתובת URL מועברת אל action הטופס יתנהג כמו רכיב הטופס HTML. כאשר פונקציה מועברת אל action הפונקציה תטפל בהגשת הטופס. הפונקציה המועברת אל action עשויה להיות אסינכרונית ותכיל את הארגומנט [K_1] (__0) ניתן לעקוף את הטופס action על ידי תכונה formAction ברכיב <button>, <input type="submit"> או <input type="image">.
אזהרות
- כאשר פונקציה מועברת ל-
actionאוformAction, שיטת ה-HTTP תהיה POST ללא קשר לערך של הפרופסmethod.
שימוש
טיפול בהגשת טופס בלקוח
העבירו פונקציה למאפיין action של הטופס כדי להפעיל את הפונקציה כאשר הטופס נשלח. formData יועבר לפונקציה כארגומנט כדי שתוכל לגשת לנתונים שנשלחו על ידי הטופס. זה שונה מהפעולה הרגילה של HTML, שמקבלת רק כתובות URL.
export default function Search() { function search(formData) { const query = formData.get("query"); alert(`You searched for '${query}'`); } return ( <form action={search}> <input name="query" /> <button type="submit">Search</button> </form> ); }
טיפול בהגשת טופס עם פעולת שרת
עיבוד <form> עם כפתור קלט ושליחה. העבירו פעולת שרת (פונקציה המסומנת ב-'use server') למאפיין action של הטופס כדי להפעיל את הפונקציה כאשר הטופס נשלח.
העברת פעולת שרת ל-<form action> מאפשרת ל-users לשלוח טפסים ללא JavaScript מופעל או לפני שהקוד נטען. זה מועיל ל-users שיש להם חיבור איטי, מכשיר או ש-JavaScript מושבתים ודומה לאופן שבו טפסים עובדים כאשר כתובת URL מועברת ל-action מאפיין.
אתה יכול use שדות טפסים מוסתרים כדי לספק נתונים לפעולה של <form>. פעולת השרת תיקרא עם נתוני שדה הטופס המוסתרים כמופע של FormData.
import { updateCart } from './lib.js';
function AddToCart({productId}) {
async function addToCart(formData) {
'use server'
const productId = formData.get('productId')
await updateCart(productId)
}
return (
<form action={addToCart}>
<input type="hidden" name="productId" value={productId} />
<button type="submit">Add to Cart</button>
</form>
);
}במקום שימוש בשדות טופס מוסתרים כדי לספק נתונים לפעולה של <form>, אתה יכול לקרוא לשיטת bind כדי לספק לה ארגומנטים נוספים. זה יקשר ארגומנט חדש (productId) לפונקציה בנוסף ל-formData שמועבר כארגומנט לפונקציה.
import { updateCart } from './lib.js';
function AddToCart({productId}) {
async function addToCart(productId, formData) {
"use server";
await updateCart(productId)
}
const addProductToCart = addToCart.bind(null, productId);
return (
<form action={addProductToCart}>
<button type="submit">Add to Cart</button>
</form>
);
}כאשר <form> מוצג על ידי רכיב שרת, ו-פעולת שרת מועברת למאפיין action של <form>, הטופס [__TK_3] משופר בהדרגה
הצג state בהמתנה במהלך שליחת הטופס
כדי להציג state בהמתנה כאשר טופס נשלח, אתה יכול לקרוא ל-useFormStatus Hook ברכיב שעובד ב-<form> ולקרוא את המאפיין pending שהוחזר.
כאן, אנו use המאפיין pending כדי לציין שהטופס נשלח.
import { useFormStatus } from "react-dom"; import { submitForm } from "./actions.js"; function Submit() { const { pending } = useFormStatus(); return ( <button type="submit" disabled={pending}> {pending ? "Submitting..." : "Submit"} </button> ); } function Form({ action }) { return ( <form action={action}> <Submit /> </form> ); } export default function App() { return <Form action={submitForm} />; }
למידע נוסף על useFormStatus Hook עיין בתיעוד ההפניה.
עדכון אופטימי של נתוני טופס
ה-useOptimistic Hook מספק דרך לעדכן בצורה אופטימית את ממשק user לפני שתסתיים פעולת רקע, כמו בקשת רשת. בהקשר של טפסים, טכניקה זו עוזרת לגרום לאפליקציות להרגיש רספונסיביות יותר. כאשר user שולח טופס, במקום לחכות לתגובת השרת שתשקף את השינויים, הממשק מתעדכן מיד בתוצאה הצפויה.
לדוגמה, כאשר user מקליד הודעה בטופס ולוחץ על כפתור “שלח”, ה-useOptimistic Hook מאפשר להודעה להופיע מיד ברשימה עם תווית “שולח…”, עוד לפני שההודעה נשלחה בפועל לשרת. גישה “אופטימית” זו נותנת רושם של מהירות והיענות. לאחר מכן, הטופס מנסה לשלוח באמת את ההודעה ברקע. לאחר שהשרת מאשר שההודעה התקבלה, התווית “שולח…” מוסרת.
import { useOptimistic, useState, useRef } from "react"; import { deliverMessage } from "./actions.js"; function Thread({ messages, sendMessage }) { const formRef = useRef(); async function formAction(formData) { addOptimisticMessage(formData.get("message")); formRef.current.reset(); await sendMessage(formData); } const [optimisticMessages, addOptimisticMessage] = useOptimistic( messages, (state, newMessage) => [ ...state, { text: newMessage, sending: true } ] ); return ( <> {optimisticMessages.map((message, index) => ( <div key={index}> {message.text} {!!message.sending && <small> (Sending...)</small>} </div> ))} <form action={formAction} ref={formRef}> <input type="text" name="message" placeholder="Hello!" /> <button type="submit">Send</button> </form> </> ); } export default function App() { const [messages, setMessages] = useState([ { text: "Hello there!", sending: false, key: 1 } ]); async function sendMessage(formData) { const sentMessage = await deliverMessage(formData.get("message")); setMessages([...messages, { text: sentMessage }]); } return <Thread messages={messages} sendMessage={sendMessage} />; }
טיפול בשגיאות שליחת טופס
במקרים מסוימים הפונקציה שנקראת על ידי action של <form> זורקת שגיאה. אתה יכול לטפל בשגיאות אלה על ידי עטיפה של <form> ב-Error Boundary. אם הפונקציה הנקראת על ידי משענת action של <form> זורקת שגיאה, החזרה לגבול השגיאה תוצג.
import { ErrorBoundary } from "react-error-boundary"; export default function Search() { function search() { throw new Error("search error"); } return ( <ErrorBoundary fallback={<p>There was an error while submitting the form</p>} > <form action={search}> <input name="query" /> <button type="submit">Search</button> </form> </ErrorBoundary> ); }
הצג שגיאת שליחת טופס ללא JavaScript
הצגת הודעת שגיאה של שליחת טופס לפני טעינת החבילה JavaScript לצורך שיפור מתקדם דורשת:
<form>יעובדו על ידי רכיב שרת- הפונקציה המועברת למפרץ
actionשל<form>תהיה פעולת שרת - ה-
useFormStateHook יהיה used כדי להציג את הודעת השגיאה
useFormState לוקח שני פרמטרים: פעולת שרת ו-state ראשוני. useFormState מחזיר שני ערכים, משתנה state ופעולה. הפעולה המוחזרת על ידי useFormState צריכה להיות מועברת ל-action של הטופס. המשתנה state המוחזר על ידי useFormState יכול להיות used כדי להציג הודעת שגיאה. הערך המוחזר על ידי פעולת השרת המועבר ל-useFormState יהיה used כדי לעדכן את המשתנה state.
import { useFormState } from "react-dom"; import { signUpNewUser } from "./api"; export default function Page() { async function signup(prevState, formData) { "use server"; const email = formData.get("email"); try { await signUpNewUser(email); alert(`Added "${email}"`); } catch (err) { return err.toString(); } } const [message, formAction] = useFormState(signup, null); return ( <> <h1>Signup for my newsletter</h1> <p>Signup with the same email twice to see an error</p> <form action={formAction} id="signup-form"> <label htmlFor="email">Email: </label> <input name="email" id="email" placeholder="react@example.com" /> <button>Sign up</button> {!!message && <p>{message}</p>} </form> </> ); }
למידע נוסף על עדכון state מפעולת טופס עם המסמכים useFormState
טיפול במספר סוגי הגשה
ניתן לעצב טפסים כך שיטפלו בפעולות הגשה מרובות בהתבסס על הכפתור שנלחץ על ידי ה-user. ניתן לשייך כל כפתור בתוך טופס לפעולה או התנהגות מובחנים על ידי הגדרת הפרופס formAction.
כאשר user מקיש על כפתור ספציפי, הטופס נשלח, ופעולה מתאימה, המוגדרת על ידי התכונות והפעולה של אותו כפתור, מבוצעת. לדוגמה, טופס עשוי לשלוח מאמר לבדיקה כברירת מחדל, אך יש לו לחצן נפרד עם formAction מוגדר לשמור את המאמר כטיוטה.
export default function Search() { function publish(formData) { const content = formData.get("content"); const button = formData.get("button"); alert(`'${content}' was published with the '${button}' button`); } function save(formData) { const content = formData.get("content"); alert(`Your draft of '${content}' has been saved!`); } return ( <form action={publish}> <textarea name="content" rows={4} cols={40} /> <br /> <button type="submit" name="button" value="submit">Publish</button> <button formAction={save}>Save draft</button> </form> ); }