Reactì useFormStatus í ì ë§ì€í°íì¬ ìíí ìì ì ì¶ ì²ëЬ, ì§í ìí© ì¶ì ë° í¥ìë ì¬ì©ì 겜íì 구ííìžì. ê²¬ê³ íê³ ì¬ì©ì ì¹íì ìž ììì ë§ëë ë°©ë²ì ë°°ì볎ìžì.
React useFormStatus: ìì ì ì¶ ìí ë° ì§í ìí© ì¶ì ì ìí ì¢ í© ê°ìŽë
ìì(Form)ì ìë§ì ì¹ ì í늬ìŒìŽì
ì íµì¬ìŽë©°, ì¬ì©ì ìížìì©ì ìí 죌ì ìží°íìŽì€ ìí ì í©ëë€. íì§ë§ ìì ì ì¶ êŽëЬ, ì€ë¥ ì²ëЬ, ì¬ì©ììê² íŒëë°± ì ê³µì ë³µì¡í ìì
ìŽ ë ì ììµëë€. Reactì useFormStatus í
ì ìŽ ê³Œì ì ëšìííì¬, ìì ì ì¶ ìí륌 ì¶ì íê³ ë ì§êŽì ìž ì¬ì©ì 겜íì ì ê³µíë ê°ìíë ë°©ë²ì ì ê³µí©ëë€.
useFormStatusë 묎ììžê°?
React 18ì ëì
ë useFormStatusë <form> ììì ì ì¶ ìíì ëí ì 볎륌 ì ê³µíëë¡ ì€ê³ë í
ì
ëë€. ìŽë¥Œ íµíŽ ìììŽ íì¬ ì ì¶ ì€ìžì§, ì±ê³µì ìŒë¡ ì ì¶ëìëì§, ëë ì ì¶ ì€ ì€ë¥ê° ë°ìíëì§ íìží ì ììµëë€. ìŽ ì 볎ë UI륌 ì
ë°ìŽížíê±°ë, ë²íŒì ë¹íì±ííê±°ë, ë¡ë© íìꞰ륌 볎ì¬ì£Œê±°ë, ì¬ì©ììê² ì€ë¥ ë©ìì§ë¥Œ ì ê³µíë ë° ì¬ì©ë ì ììµëë€.
useFormStatus ì¬ì©ì 죌ì ìŽì :
- ê°ìíë ìì ìí êŽëЬ: ìì ì ì¶ì ìí ìë ìí êŽëЬì íìì±ì ìì ìì©êµ¬ ìœë(boilerplate code)륌 ì€ì ëë€.
- í¥ìë ì¬ì©ì 겜í: ìì ì ì¶ ì€ì ì¬ì©ììê² ì€ìê° íŒëë°±ì ì ê³µíì¬ ì¬ì©ì±ì ëì ëë€.
- í¥ìë ì ê·Œì±: ì ì¶ ì€ì ìì ìì륌 ë¹íì±ííê³ ëª íí ì€ë¥ ë©ìì§ë¥Œ ì ê³µíì¬ ì ê·Œì± ëì ìì ìížìì©ì ê°ë¥íê² í©ëë€.
- ìµì íë ì±ë¥: ìì ì ì¶ ìí륌 íšìšì ìŒë¡ ì¶ì íì¬ ë¶íìí 늬ë ëë§ì ë°©ì§í©ëë€.
useFormStatusì ìë ë°©ì
useFormStatus í
ì <form> ìì륌 ë ëë§íë React 컎í¬ëíž ëŽìì ì¬ì©ë©ëë€. ìŽ í
ì ë€ì ìì±ì í¬íšíë ê°ì²Žë¥Œ ë°íí©ëë€:
pending: ìììŽ íì¬ ì ì¶ ì€ìžì§ë¥Œ ëíëŽë ë¶ëЬìž(boolean) ê°ì ëë€.data: ììì action íšìê° (ì±ê³µ ì) ë°íí ë°ìŽí°ì ëë€.method: ìì ì ì¶ì ì¬ì©ë HTTP ë©ìëì ëë€ (ì: "POST", "GET").action: ìììŽ ì ì¶ëìì ë ížì¶ë íšìì ëë€.error: ìì ì ì¶ìŽ ì€íší 겜ì°ì ì€ë¥ ê°ì²Žì ëë€.
useFormStatus륌 ì¬ì©íë €ë©Ž 뚌ì ììì ëí action íšì륌 ì ìíŽìŒ í©ëë€. ìŽ íšìë ìììŽ ì ì¶ë ë ížì¶ë©ëë€. action íšì ëŽìì íìí ë°ìŽí° ì²ëЬ, ì íšì± ê²ì¬ ëë API ížì¶ì ìíí ì ììµëë€. action íšìë useFormStatus í
ì data ìì±ìì ì¬ì©í ì ìë ê°ì ë°ííŽìŒ í©ëë€. ì¡ì
ìì ì€ë¥ê° ë°ìí멎 íŽë¹ ì€ë¥ë error ìì±ìì ì¬ì©í ì ììµëë€.
useFormStatusì ì€ì ìì
ìì 1: Ʞ볞 ìì ì ì¶ ì¶ì
ìŽ ìì ë useFormStatus륌 ì¬ì©íì¬ ê°ëší 묞ì ììì ì ì¶ ìí륌 ì¶ì íë ë°©ë²ì 볎ì¬ì€ëë€. ìŽ ìì ë Next.jsë Remixì ê°ì íë ììí¬ê° íìí React ìë² ì»Ží¬ëíž(RSC)ìì ìëí©ëë€.
// app/contact/page.tsx (Next.js)
'use client';
import { useFormStatus } from 'react-dom';
async function submitForm(formData: FormData) {
"use server";
// Simulate an API call
await new Promise((resolve) => setTimeout(resolve, 2000));
const name = formData.get('name') as string;
const email = formData.get('email') as string;
const message = formData.get('message') as string;
if (!name || !email || !message) {
throw new Error('Please fill in all fields.');
}
console.log('Form Data:', { name, email, message });
return { message: 'Form submitted successfully!' };
}
export default function ContactForm() {
const { pending, data, error } = useFormStatus();
return (
);
}
ìŽ ìì ììë pending ìí륌 ì¬ì©íì¬ ìììŽ ì ì¶ëë ëì ìì ì
ë ¥ê³Œ ì ì¶ ë²íŒì ë¹íì±íí©ëë€. ëí ë²íŒ í
ì€ížë¥Œ "Submitting..."ìŒë¡ ëì ìŒë¡ ë³ê²œíì¬ ì¬ì©ììê² ìê°ì íŒëë°±ì ì ê³µí©ëë€. ì±ê³µ ì submitForm ì¡ì
ì dataê° íìë©ëë€. ì ì¶ ì€ì ì€ë¥ê° ë°ìí멎 error ë©ìì§ê° ì¬ì©ììê² íìë©ëë€.
ìì 2: ë¡ë© íìêž° 볎ì¬ì£Œêž°
ìŽ ìì ë ìììŽ ì ì¶ëë ëì ë¡ë© íìꞰ륌 íìíë ë°©ë²ì 볎ì¬ì€ëë€. ìŽë ꞎ API ížì¶ìŽë ë³µì¡í ë°ìŽí° ì²ëŠ¬ê° í¬íšë ììì í¹í ì ì©í©ëë€.
// Similar component structure as Example 1
export default function ContactForm() {
const { pending, data, error } = useFormStatus();
return (
);
}
ìŽ ìì ììë pending ìíê° trueìŒ ë ê°ëší "Loading..." ë©ìì§ê° íìë©ëë€. ìŽë¥Œ ì€íŒëë ì§íë¥ íìì€ê³Œ ê°ì ë ì êµí ë¡ë© íìêž°ë¡ ë첎í ì ììµëë€.
ìì 3: ìì ì íšì± ê²ì¬ ì€ë¥ ì²ëЬíêž°
ìŽ ìì ë useFormStatus륌 ì¬ì©íì¬ ìì ì íšì± ê²ì¬ ì€ë¥ë¥Œ ì²ëЬíë ë°©ë²ì 볎ì¬ì€ëë€. action íšìë ì íšì± ê²ì¬ë¥Œ ìííê³ ì íšì± ê²ì¬ ê·ì¹ì ìë°í멎 ì€ë¥ë¥Œ ë°ììíµëë€.
// Similar component structure as Example 1
async function submitForm(formData: FormData) {
"use server";
const name = formData.get('name') as string;
const email = formData.get('email') as string;
const message = formData.get('message') as string;
if (!name) {
throw new Error('Name is required.');
}
if (!email) {
throw new Error('Email is required.');
}
if (!message) {
throw new Error('Message is required.');
}
// Simulate an API call
await new Promise((resolve) => setTimeout(resolve, 2000));
console.log('Form Data:', { name, email, message });
return { message: 'Form submitted successfully!' };
}
export default function ContactForm() {
const { pending, data, error } = useFormStatus();
return (
);
}
ìŽ ìì ìì action íšìë ìŽëŠ, ìŽë©ìŒ, ë©ìì§ íëê° ë¹ìŽ ìëì§ íìží©ëë€. ìŽ íë ì€ íëëŒë ë¹ìŽ ììŒë©Ž íŽë¹ ë©ìì§ì íšê» ì€ë¥ë¥Œ ë°ììíµëë€. ê·žë¬ë©Ž useFormStatus í
ì error ìì±ì ì¬ì©íì¬ ì¬ì©ììê² ì€ë¥ ë©ìì§ë¥Œ íìí©ëë€.
ê³ êž ì¬ì© ì¬ë¡ ë° ê³ ë € ì¬í
ìëíí° ìì ëŒìŽëžë¬ëЬìì íµí©
useFormStatusë ìì ì ì¶ ìí륌 ì¶ì íë ë€ìŽí°ëž ì룚ì
ì ì ê³µíì§ë§ FormikìŽë React Hook Form곌 ê°ì ìëíí° ìì ëŒìŽëžë¬ëЬìë íµí©í ì ììµëë€. ìŽë¬í ëŒìŽëžë¬ëЬë ìì ì íšì± ê²ì¬, íë êŽëЬ, ìí êŽëЬì ê°ì ë ê³ êž êž°ë¥ì ì ê³µí©ëë€. useFormStatus륌 ìŽë¬í ëŒìŽëžë¬ëЬì ê²°í©í멎 ê³ ëë¡ ì¬ì©ì ì ì ê°ë¥íê³ ê²¬ê³ í ììì ë§ë€ ì ììµëë€.
FormikìŽë React Hook Form곌 íµí©íë €ë©Ž ê° ëŒìŽëžë¬ëЬì ìì ì ì¶ ížë€ë¬ë¥Œ íì©íê³ useFormStatus륌 ì¬ì©íì¬ ì 첎 ì ì¶ ìí륌 ì¶ì í ì ììµëë€. ì¬ì í ìë² ì¡ì
(Server Action)ì ë§ë€ìŽìŒ í ê°ë¥ì±ìŽ ëì§ë§, íŽëŒìŽìžíž ìž¡ ìì ìí êŽëЬë ì íí ëŒìŽëžë¬ëЬìì ì²ëЬë©ëë€.
ë¹ëêž° ìì ì²ëЬ
ë§ì ìììë API ížì¶ìŽë ë°ìŽí°ë² ìŽì€ 쿌늬ì ê°ì ë¹ëêž° ìì
ìŽ í¬íšë©ëë€. ë¹ëêž° ìì
ì ë€ë£° ëë ìì ì ì¶ìŽ ì¬ë°ë¥Žê² ì²ëЬëê³ ì¬ì©ììê² ì ì í íŒëë°±ìŽ ì ê³µëëë¡ íë ê²ìŽ ì€ìí©ëë€. useFormStatus í
ì ìììŽ ë¹ëêž° ìì
ìŽ ìë£ëꞰ륌 êž°ë€ëŠ¬ê³ ììì ëíëŽë ë° ì¬ì©í ì ìë pending ìí륌 ì ê³µíì¬ ìŽ ê³Œì ì ëšìíí©ëë€.
ë¹ëêž° ìì
ì€ì ë°ìí ì ìë 몚ë ì€ë¥ë¥Œ ì ìì ìŒë¡ ì²ëЬíêž° ìíŽ ê°ë ¥í ì€ë¥ ì²ëЬ êž°ë¥ì 구ííë ê²ë ì€ìí©ëë€. useFormStatus í
ì error ìì±ì ì¬ì©íì¬ ì¬ì©ììê² ì€ë¥ ë©ìì§ë¥Œ íìí ì ììµëë€.
ì ê·Œì± ê³ ë € ì¬í
ì ê·Œì±ì ì¹ ê°ë°ì ì€ìí 잡멎ìŽë©°, ììë ììžë ìëëë€. ììì ë§ë€ ëë ì¥ì ê° ìë ì¬ì©ìë ì ê·Œí ì ìëë¡ ë³Žì¥íë ê²ìŽ ì€ìí©ëë€. useFormStatus í
ì ë€ìì íµíŽ ìì ì ê·Œì±ì í¥ììí€ë ë° ì¬ì©ë ì ììµëë€:
- ì ì¶ ì€ ìì ìì ë¹íì±í: ì¬ì©ìê° ì€ìë¡ ììì ì¬ë¬ ë² ì ì¶íë ê²ì ë°©ì§í©ëë€.
- ëª íí ì€ë¥ ë©ìì§ ì ê³µ: ì€ë¥ ë©ìì§ë ê°ê²°íê³ ì ì©íë©° ìœê² ìŽíŽí ì ììŽìŒ í©ëë€. ëí ARIA ìì±ì ì¬ì©íì¬ íŽë¹ ìì íëì ì°ê²°ëìŽìŒ í©ëë€.
- ARIA ìì± ì¬ì©: ARIA ìì±ì 볎조 êž°ì ì ìì ë° íŽë¹ ììì ëí ì¶ê° ì 볎륌 ì ê³µíë ë° ì¬ì©í ì ììµëë€. ì륌 ë€ìŽ,
aria-describedbyìì±ì ì€ë¥ ë©ìì§ë¥Œ ìì íëì ì°ê²°íë ë° ì¬ì©í ì ììµëë€.
ì±ë¥ ìµì í
useFormStatusë ìŒë°ì ìŒë¡ íšìšì ìŽì§ë§ ë³µì¡í ììì ë§ë€ ëë ì±ë¥ì 믞ì¹ë ìí¥ì ê³ ë €íë ê²ìŽ ì€ìí©ëë€. useFormStatus륌 ì¬ì©íë 컎í¬ëíž ëŽìì ë¹ì©ìŽ ë§ìŽ ëë ê³ì°ìŽë API ížì¶ì ìííì§ ë§ìžì. ëì ìŽë¬í ìì
ì action íšìì ììíìžì.
ëí ë¶íìí 늬ë ëë§ì ì ìíìžì. Reactì ë©ëªšìŽì ìŽì
êž°ì (ì: React.memo, useMemo, useCallback)ì ì¬ì©íì¬ propsê° ë³ê²œëì§ ìë í 컎í¬ëížê° 늬ë ëë§ëë ê²ì ë°©ì§íìžì.
useFormStatus ì¬ì©ì ìí ëªšë² ì¬ë¡
actioníšì륌 ê°ê²°íê³ ì§ì€ì ìŒë¡ ì ì§íìžì:actioníšìë ì£Œë¡ ë°ìŽí° ì²ëЬ, ì íšì± ê²ì¬ ë° API ížì¶ì ì²ëЬíŽìŒ í©ëë€.actioníšì ëŽìì ë³µì¡í UI ì ë°ìŽížë êž°í ë¶ì íšê³Œë¥Œ ìííì§ ë§ìžì.- ì¬ì©ììê² ëª
ííê³ ì ì©í íŒëë°±ì ì ê³µíìžì:
useFormStatusí ìpending,data,errorìì±ì ì¬ì©íì¬ ìì ì ì¶ ì€ì ì¬ì©ììê² ì€ìê° íŒëë°±ì ì ê³µíìžì. - ê°ë ¥í ì€ë¥ ì²ëŠ¬ë¥Œ 구ííìžì: ìì ì ì¶ ì€ì ë°ìí ì ìë 몚ë ì€ë¥ë¥Œ ì ìì ìŒë¡ ì²ëЬíê³ ì¬ì©ììê² ì ì©í ì€ë¥ ë©ìì§ë¥Œ ì ê³µíìžì.
- ì ê·Œì±ì ê³ ë €íìžì: ì ê·Œì± ëªšë² ì¬ë¡ë¥Œ ë°ëŒ ì¥ì ê° ìë ì¬ì©ìë ììì ì ê·Œí ì ìëë¡ íìžì.
- ì±ë¥ì ìµì ííìžì:
useFormStatus륌 ì¬ì©íë 컎í¬ëíž ëŽìì ë¶íìí 늬ë ëë§ê³Œ ë¹ì©ìŽ ë§ìŽ ëë ê³ì°ì íŒíìžì.
ì ìžê³ì ì€ì ì ì© ì¬ë¡ ë° ìì
useFormStatus í
ì ë€ìí ì°ì
곌 ì§ìì ê±žì³ ë€ìí ìì êž°ë° ìë늬ì€ì ì ì©ë ì ììµëë€. ë€ìì ëª ê°ì§ ìì
ëë€:
- ì ì ìê±°ë (êžë¡ë²): ìšëŒìž ìì ì
useFormStatus륌 ì¬ì©íì¬ ì£Œë¬ž ìì ì ì¶ì ì¶ì í ì ììµëë€.pendingìíë ì£Œë¬žìŽ ì²ëЬëë ëì "죌묞íêž°" ë²íŒì ë¹íì±ííë ë° ì¬ì©í ì ìê³ ,errorìíë 죌묞 ì ì¶ìŽ ì€íší 겜ì°(ì: ê²°ì 묞ì ëë ì¬ê³ ë¶ì¡±) ì€ë¥ ë©ìì§ë¥Œ íìíë ë° ì¬ì©í ì ììµëë€. - ìë£ (ì ëœ): ìë£ ìë¹ì€ ì ê³µìë
useFormStatus륌 ì¬ì©íì¬ íì ë±ë¡ ìì ì ì¶ì ì¶ì í ì ììµëë€.pendingìíë íì ì ë³Žê° ì²ëЬëë ëì ë¡ë© íìꞰ륌 íìíë ë° ì¬ì©í ì ìê³ ,dataìíë ì±ê³µì ìž ë±ë¡ ì íìž ë©ìì§ë¥Œ íìíë ë° ì¬ì©í ì ììµëë€. GDPR(ìŒë° ë°ìŽí° ë³Žíž ê·ì ) ì€ìê° ê°ì¥ ì€ìíë©°, ë°ìŽí° ê°ìž ì 볎 ë³Žíž ìë°ê³Œ êŽë šë ì€ë¥ ë©ìì§ë ì ì€íê² ì²ëЬíŽìŒ í©ëë€. - êµì¡ (ììì): ìšëŒìž íìµ íë«íŒì
useFormStatus륌 ì¬ì©íì¬ ê³Œì ì ë¡ë ì ì¶ì ì¶ì í ì ììµëë€.pendingìíë 곌ì ê° ì ë¡ëëë ëì "ì ì¶" ë²íŒì ë¹íì±ííë ë° ì¬ì©í ì ìê³ ,errorìíë ì ë¡ëê° ì€íší 겜ì°(ì: íìŒ í¬êž° ì í ëë ë€ížìí¬ ë¬žì ) ì€ë¥ ë©ìì§ë¥Œ íìíë ë° ì¬ì©í ì ììµëë€. êµê°ë§ë€ íì êž°ì€ê³Œ ì ì¶ ì구 ì¬íìŽ ë€ë¥Œ ì ììŒë©°, ììì ìŽë¥Œ ìì©íŽìŒ í©ëë€. - êžìµ ìë¹ì€ (ë¶ë¯ž): ìíì
useFormStatus륌 ì¬ì©íì¬ ëì¶ ì ì²ì ì ì¶ì ì¶ì í ì ììµëë€.pendingìíë ì ì²ìê° ì²ëЬëë ëì ë¡ë© íìꞰ륌 íìíë ë° ì¬ì©í ì ìê³ ,dataìíë ëì¶ ì¹ìž ìí륌 íìíë ë° ì¬ì©í ì ììµëë€. êžìµ ê·ì (ì: KYC - ê³ ê° ìêž° ì ë) ì€ìê° ì€ìíë©°, ê·ì ì€ì 묞ì ì êŽë šë ì€ë¥ ë©ìì§ë ëª ííê³ êµ¬ì²Žì ìŽìŽìŒ í©ëë€. - ì ë¶ ìë¹ì€ (ëšë¯ž): ì ë¶ êž°êŽì
useFormStatus륌 ì¬ì©íì¬ ì믌 íŒëë°± ìì ì ì¶ì ì¶ì í ì ììµëë€.pendingìíë íŒëë°±ìŽ ì²ëЬëë ëì "ì ì¶" ë²íŒì ë¹íì±ííë ë° ì¬ì©í ì ìê³ ,dataìíë ì±ê³µì ìž ì ì¶ ì íìž ë©ìì§ë¥Œ íìíë ë° ì¬ì©í ì ììµëë€. ì믌ë€ì ëì§íž 늬í°ë¬ì ìì€ê³Œ êž°ì ì ê·Œì±ìŽ ë€ìí ì ììŒë¯ë¡ ì ê·Œì±ìŽ ë§€ì° ì€ìí©ëë€. ììì ì¬ë¬ ìžìŽë¡ ì ê³µëìŽìŒ í©ëë€.
ìŒë°ì ìž ë¬žì íŽê²°
useFormStatusê° ì ë°ìŽížëì§ ìì: React 18 ìŽìì ì¬ì©íê³ ìëì§, ê·žëŠ¬ê³ ìììactionìŽ ì¬ë°ë¥Žê² ì ìëìŽ ìëì§ íìžíìžì. ìë² ì¡ì ìŽ"use server"ì§ììŽë¥Œ ì¬ì©íì¬ ì¬ë°ë¥Žê² ì ìëìëì§ íìžíìžì.- ì€ë¥ ë©ìì§ê° íìëì§ ìì:
actioníšìê° ì€ë¥ë¥Œ ì¬ë°ë¥Žê² ë°ììí€ê³ ìëì§, ê·žëŠ¬ê³ ì»Ží¬ëížììerror.message륌 íìíê³ ìëì§ ë€ì íìžíìžì. ìì ì ì¶ ì€ ìœìì ì€ë¥ê° ìëì§ ê²ì¬íìžì. - ìììŽ ì¬ë¬ ë² ì ì¶ëš: ì€ìë¡ ìží ëëž íŽëŠì ë°©ì§íêž° ìíŽ
pendingìí륌 ì¬ì©íì¬ ì ì¶ ë²íŒìŽ ë¹íì±íëëì§ íìžíìžì.
ê²°ë¡
Reactì useFormStatus í
ì ìì ì ì¶ ìí륌 ì¶ì íê³ ë ëì ì¬ì©ì 겜íì ì ê³µíë ê°ë ¥íê³ ížëЬí ë°©ë²ì ì ê³µí©ëë€. ìì ìí êŽëŠ¬ë¥Œ ëšìííê³ , ì ê·Œì±ì í¥ììí€ë©°, ì±ë¥ì ìµì ííšìŒë¡ìš useFormStatusë ê°ë°ìê° ê²¬ê³ íê³ ì¬ì©ì ì¹íì ìž ììì ë§ë€ ì ìëë¡ ì§ìí©ëë€. ê·ž êž°ë¥ê³Œ ëªšë² ì¬ë¡ë¥Œ ìŽíŽíšìŒë¡ìš React ì í늬ìŒìŽì
ìì ìííê³ ë§€ë ¥ì ìž ìì ìížìì©ì ë§ë€êž° ìíŽ useFormStatus륌 íì©í ì ììµëë€.