useFormStatus ν μ μ¬μ©νμ¬ Reactμμ νΌ μ μΆ μνλ₯Ό ν¨κ³Όμ μΌλ‘ κ΄λ¦¬νλ λ°©λ²μ μμ보μΈμ. ν₯μλ μ¬μ©μ κ²½νμ μν μμΈν μ€λͺ , μ€μ μμ λ° κΈλ‘λ² λͺ¨λ² μ¬λ‘λ₯Ό μ 곡ν©λλ€.
React useFormStatus λ§μ€ν°νκΈ°: νΌ μ μΆ μνμ λν μ’ ν© κ°μ΄λ
νλ μΉ μ ν리μΌμ΄μ
μμ νΌμ μ΄λμλ μμ΅λλ€. μ°λ½μ² νΌκ³Ό λ±λ‘ νμ΄μ§λΆν° 볡μ‘ν λ°μ΄ν° μ
λ ₯ μΈν°νμ΄μ€μ μ΄λ₯΄κΈ°κΉμ§ νΌμ μ¬μ©μ μνΈ μμ©μ μ£Όμ μλ¨μ
λλ€. μ΄λ¬ν νΌμ μν, νΉν μ μΆ νλ‘μΈμ€ μ€μ μνλ₯Ό κ΄λ¦¬νλ κ²μ μννκ³ μ§κ΄μ μΈ μ¬μ©μ κ²½νμ μ 곡νλ λ° λ§€μ° μ€μν©λλ€. React 18μ λμ
λ Reactμ useFormStatus
ν
μ νΌ μ μΆ μνλ₯Ό μ²λ¦¬νλ λ° μμ΄ κ°μνλ μ κ·Ό λ°©μμ μ 곡νμ¬ κ°λ°μκ° μ€μκ° νΌλλ°±μ μ 곡νκ³ μ 체 μ ν리μΌμ΄μ
μλ΅μ±μ ν₯μμν¬ μ μλλ‘ ν©λλ€.
νΌ μ μΆ μνμ μ€μμ± μ΄ν΄
μ¬μ©μκ° νΌμ μ μΆνλ©΄ μ¬λ¬ μνκ° μ‘΄μ¬ν μ μμ΅λλ€. μ΄κΈ° μν, μ μΆ μν(λ°μ΄ν° μ μ‘ μ€) λ° μλ£λ μν(μ±κ³΅ λλ μ€λ₯)κ° μμ΅λλ€. μ΄λ¬ν μνλ₯Ό μ¬μ©μμκ² μ ννκ² λ°μνλ κ²μ μ¬λ¬ κ°μ§ μ΄μ λ‘ μ€μν©λλ€.
- μ¬μ©μ νΌλλ°±: λ‘λ© νμκΈ° λλ μ±κ³΅ λ©μμ§μ κ°μ λͺ νν μκ°μ μ νΈλ₯Ό μ 곡νλ©΄ μ¬μ©μμκ² μμ μ΄ μ²λ¦¬ μ€μμ μ립λλ€. μ΄λ κ² νλ©΄ μ¬μ©μκ° μ’μ νκ±°λ νΌμ λ°λ³΅μ μΌλ‘ μ μΆνλ κ²μ λ°©μ§ν μ μμ΅λλ€.
- μ€λ₯ μ²λ¦¬: μ μ΅ν μ€λ₯ λ©μμ§λ₯Ό νμνλ©΄ μ¬μ©μκ° λ¬΄μμ΄ μλͺ»λμλμ§, μ λ ₯μ μμ νλ λ°©λ²μ μ΄ν΄νλ λ° λμμ΄ λ©λλ€. μ΄λ λ λμ μ¬μ©μ κ²½νμΌλ‘ μ΄μ΄μ§κ³ μ§μ μμ²μ μ€μ λλ€.
- ν₯μλ μ¬μ©μ±: μ μΆ μν μ€μ μ μΆ λ²νΌμ λΉνμ±ννλ©΄ μ¬λ¬ λ² μ μΆνλ κ²μ λ°©μ§νμ¬ λ°μ΄ν° λΆμΌμΉ λλ λΆνμν μλ² λ‘λλ₯Ό λ°©μ§ν μ μμ΅λλ€.
- μ κ·Όμ±: νΌ μνλ₯Ό μ¬λ°λ₯΄κ² κ΄λ¦¬νλ©΄ μ₯μ κ° μλ μ¬μ©μμ μ κ·Όμ±μ΄ ν₯μλμ΄ λμ± ν¬κ΄μ μ΄κ³ μ¬μ©μ μΉνμ μΈ κ²½νμ 보μ₯ν μ μμ΅λλ€.
Reactμ useFormStatus
ν
μκ°
useFormStatus
ν
μ νΌ μ μΆμ νμ¬ μνμ λν μ 보λ₯Ό μ 곡νμ¬ νΌ μ μΆ μν κ΄λ¦¬ νλ‘μΈμ€λ₯Ό λ¨μνν©λλ€. λ€μκ³Ό κ°μ λͺ κ°μ§ μ£Όμ μμ±μ μ 곡ν©λλ€.
pending
: νΌμ΄ νμ¬ μ μΆ μ€μΈμ§ μ¬λΆλ₯Ό λνλ΄λ λΆμΈμ λλ€.method
: νΌ μ μΆμ μ¬μ©λ HTTP λ©μλμ λλ€(μ: 'GET', 'POST').action
: νΌμ΄ μ μΆλλ URLμ λλ€.formData
: μ μΆλλ νΌ λ°μ΄ν°μ λλ€.
μ΄ ν μ λΈλΌμ°μ μ λ΄μ₯λ νΌ μ²λ¦¬μ μννκ² μλνλ©° React μ»΄ν¬λνΈ λ΄μμ νΌ μνλ₯Ό κ΄λ¦¬νλ κΉλνκ³ μ μΈμ μΈ λ°©λ²μ μ 곡ν©λλ€.
μ€μ ꡬν: κΈ°λ³Έ νΌ μ μΆ μν
κ°λ¨ν μ°λ½μ² νΌμ λ§λ€κ³ useFormStatus
λ₯Ό μ¬μ©νμ¬ μ μΆ μνλ₯Ό κ΄λ¦¬νλ λ°©λ²μ 보μ¬λλ¦¬κ² μ΅λλ€. κΈ°λ³Έ νΌ κ΅¬μ‘°λΆν° μμνκ² μ΅λλ€.
import React from 'react';
import { useFormStatus } from 'react-dom';
function ContactForm() {
const { pending } = useFormStatus();
return (
);
}
export default ContactForm;
μ΄ μμ μμ:
'react-dom'
μμuseFormStatus
λ₯Ό κ°μ Έμ΅λλ€.- ν
μ μ¬μ©νμ¬
pending
μνλ₯Ό κ°μ Έμ΅λλ€. pending
μ΄ trueμ΄λ©΄ μ μΆ λ²νΌμ λΉνμ±νν©λλ€.- νΌμ΄ μ μΆλλ λμ λ²νΌ ν μ€νΈλ₯Ό "Submitting..."μΌλ‘ λ³κ²½ν©λλ€.
μ΄λ κ² νλ©΄ μ¬μ©μμκ² μ μΆμ΄ μ§ν μ€μμ λνλ΄λ μ¦κ°μ μΈ μκ°μ νΌλλ°±μ΄ μ 곡λ©λλ€.
κ³ κΈ μμ : λ‘λ© νμκΈ° λ° μ±κ³΅/μ€λ₯ λ©μμ§ κ΅¬ν
μ°λ½μ² νΌμ κ°μ νμ¬ λ‘λ© νμκΈ°λ₯Ό ν¬ν¨νκ³ μ μΆ μ μ±κ³΅ λλ μ€λ₯ λ©μμ§λ₯Ό νμν΄ λ³΄κ² μ΅λλ€. μ΄λ κ² νλ©΄ λμ± μΈλ ¨λ μ¬μ©μ κ²½νμ΄ λ§λ€μ΄μ§λλ€.
import React, { useState } from 'react';
import { useFormStatus } from 'react-dom';
function ContactForm() {
const { pending } = useFormStatus();
const [submissionResult, setSubmissionResult] = useState(null);
const handleSubmit = async (event) => {
event.preventDefault();
try {
const formData = new FormData(event.target);
const response = await fetch('/api/contact', {
method: 'POST',
body: formData,
});
if (response.ok) {
setSubmissionResult({ success: true, message: 'Message sent successfully!' });
event.target.reset(); // Clear the form
} else {
const errorData = await response.json();
setSubmissionResult({ success: false, message: errorData.message || 'An error occurred.' });
}
} catch (error) {
setSubmissionResult({ success: false, message: 'An unexpected error occurred.' });
}
};
return (
);
}
export default ContactForm;
μ΄ μμ μ μ£Όμ κ°μ μ¬ν:
- μν κ΄λ¦¬:
useState
ν μ μ¬μ©νμ¬ μ±κ³΅ λλ μ€λ₯ λ©μμ§λ₯Ό μ μ₯νλsubmissionResult
λ₯Ό κ΄λ¦¬ν©λλ€. - νΌ μ²λ¦¬:
handleSubmit
ν¨μλ νΌ μ μΆ μ νΈμΆλμ΄ κΈ°λ³Έ λΈλΌμ°μ μ μΆ λμμ λ°©μ§ν©λλ€. - API μνΈ μμ©:
fetch
APIλ₯Ό μ¬μ©νμ¬ νΌ λ°μ΄ν°λ₯Ό λ°±μλ API μλν¬μΈνΈ(/api/contact
)λ‘ λ³΄λ λλ€. μ€μ API μλν¬μΈνΈλ‘ λ°κΏλλ€. - μ€λ₯ μ²λ¦¬:
try...catch
λΈλ‘μ ν¬ν¨νκ³ μλ΅ μνλ₯Ό νμΈνμ¬ μ μΆ μ€ μ μ¬μ μΈ μ€λ₯λ₯Ό μ²λ¦¬ν©λλ€. μ΄λ κ² νλ©΄ μ μ ν μ€λ₯ λ©μμ§λ₯Ό νμν μ μμ΅λλ€. - μ±κ³΅/μ€λ₯ λ©μμ§: API μλ΅μ λ°λΌ μ±κ³΅ λλ μ€λ₯ λ©μμ§λ₯Ό 쑰건λΆλ‘ λ λλ§ν©λλ€. λν μ±κ³΅μ μΈ μ μΆ μ νΌμ μ¬μ€μ ν©λλ€.
- CSS μ€νμΌ μ§μ : (μ€νμΌ μ§μ μ μν΄ CSSμ μ΄λ¬ν ν΄λμ€λ₯Ό μΆκ°νλ κ²μ κ³ λ €νμμμ€)
.success-message { color: green; }
.error-message { color: red; }
κΈλ‘λ² κ³ λ € μ¬ν: κ΅μ μ¬μ©μλ₯Ό μν λͺ¨λ² μ¬λ‘
κΈλ‘λ² μ¬μ©μλ₯Ό μν νΌμ λμμΈν λλ ν¬κ΄μ±κ³Ό κΈμ μ μΈ μ¬μ©μ κ²½νμ 보μ₯νκΈ° μν΄ λ€μν μμλ₯Ό κ³ λ €νλ κ²μ΄ μ€μν©λλ€.
- νμ§ν: λͺ¨λ νΌ λ μ΄λΈ, λ©μμ§ λ° μ€λ₯ λ©μμ§λ₯Ό μ¬μ©μμ μ νΈ μΈμ΄λ‘ λ²μν©λλ€. λ²μ λΌμ΄λΈλ¬λ¦¬ λλ μλΉμ€λ₯Ό μ¬μ©νμ¬ μ΄ νλ‘μΈμ€λ₯Ό μλννλ κ²μ κ³ λ €νμμμ€.
- λ μ§ λ° μκ° νμ: νΌλμ νΌνκ³ λͺ νμ±μ 보μ₯νκΈ° μν΄ κ΅μ λ μ§ λ° μκ° νμ(μ: YYYY-MM-DD)μ μ¬μ©ν©λλ€. μμ νμμ μμ λ₯Ό νμν©λλ€.
- ν΅ν νμ: νΌμ κΈμ΅ κ±°λκ° ν¬ν¨λ κ²½μ° ν΅ν κΈ°νΈ λ° νμμ λͺ ννκ² νμν©λλ€. μ¬μ©μμ μμΉμ λ°λΌ ν΅νλ₯Ό μλμΌλ‘ κ°μ§νκ±°λ ν΅νλ₯Ό μ ννλλ‘ νμ©νλ κ²μ κ³ λ €νμμμ€.
- μ ν λ²νΈ μ λ ₯: μ¬μ©μκ° κ΅κ°μ κ΄κ³μμ΄ μ ν λ²νΈλ₯Ό μ ννκ² μ λ ₯ν μ μλλ‘ κ΅κ° μ½λ μ νκΈ° λλ λ§μ€ν¬λ μ λ ₯ νλλ₯Ό μ ν λ²νΈμ μ 곡ν©λλ€.
- μ£Όμ νλ: μ¬μ©μκ° κ΅μ μ£Όμ νμμ λμμ΄ λλ μ£Όμ μλ μμ± μλΉμ€λ₯Ό μ¬μ©νμ¬ μ£Όμλ₯Ό λΉ λ₯΄κ³ μ ννκ² μ λ ₯ν μ μλλ‘ κ³ λ €νμμμ€.
- μ λ ₯ μ ν¨μ± κ²μ¬: μ¬μ©μκ° μ ν¨ν λ°μ΄ν°λ₯Ό μ λ ₯ν μ μλλ‘ κ°λ ₯ν μ λ ₯ μ ν¨μ± κ²μ¬λ₯Ό ꡬνν©λλ€. λ¬Έμ μ μμ λ°©λ²μ μ€λͺ νλ λͺ ννκ³ κ°κ²°ν μ€λ₯ λ©μμ§λ₯Ό μ 곡ν©λλ€.
- μ κ·Όμ±: νΌμ΄ μ₯μ κ° μλ μ¬μ©μκ° μ‘μΈμ€ν μ μλμ§ νμΈν©λλ€. μ¬κΈ°μλ μλ§¨ν± HTML μ¬μ©, μ΄λ―Έμ§μ λν λ체 ν μ€νΈ μ 곡, ν€λ³΄λλ₯Ό μ¬μ©νμ¬ νΌμ νμν μ μλμ§ νμΈμ΄ ν¬ν¨λ©λλ€. μ€ν¬λ¦° 리λλ‘ ν μ€νΈν©λλ€.
- 보μ: νΉν κ°μΈ μλ³ μ 보(PII)λ₯Ό μ μ‘ν λ μμ ν μ½λ© λ°©μμΌλ‘ μ¬μ©μ λ°μ΄ν°λ₯Ό 보νΈν©λλ€. HTTPSλ₯Ό μ¬μ©νκ³ μ λ ₯ μμ λ° κ΅μ°¨ μ¬μ΄νΈ μ€ν¬λ¦½ν (XSS) λ°©μ§μ κ°μ μ‘°μΉ κ΅¬νμ κ³ λ €νμμμ€.
κ³ κΈ κΈ°μ : 볡μ‘ν νΌμ useFormStatus
νμ©
κΈ°λ³Έ μμ λ μ μ©νμ§λ§ useFormStatus
λ₯Ό λ³΄λ€ λ³΅μ‘ν μλ리μ€μμ μ¬μ©ν μ μμ΅λλ€.
1. μ¬λ¬ μ μΆ λ²νΌ
μ¬λ¬ μ μΆ λ²νΌμ΄ μλ νΌ(μ: "μ μ₯ λ° λ«κΈ°" λ° "μ μ₯ λ° μλ‘ λ§λ€κΈ°")μμ κ° λ²νΌμ λν΄ useFormStatus
ν
μ μ¬μ©ν μ μμ΅λλ€. μ΄λ κ² νλ©΄ ν΄λΉ λ²νΌμ μμ
κ³Ό κ΄λ ¨λ μ μΆ μνμ λ°λΌ λ€λ₯Έ λ‘λ© μνλ₯Ό νμνκ±°λ νΉμ λ²νΌμ λΉνμ±νν μ μμ΅λλ€.
import React from 'react';
import { useFormStatus } from 'react-dom';
function MyForm() {
const saveAndCloseStatus = useFormStatus({
action: '/api/save-and-close'
});
const saveAndNewStatus = useFormStatus({
action: '/api/save-and-new'
});
return (
);
}
export default MyForm;
μ¬κΈ°μ action
μ΅μ
μ μ¬μ©νμ¬ μΆμ ν λ²νΌμ μ μΆ μνλ₯Ό μ§μ ν©λλ€.
2. νΌ μ ν¨μ± κ²μ¬ νΌλλ°±
νΌ μ ν¨μ± κ²μ¬ λΌμ΄λΈλ¬λ¦¬(μ: Formik, React Hook Form)μ useFormStatus
λ₯Ό κ²°ν©νμ¬ μ ν¨μ± κ²μ¬ νλ‘μΈμ€ μ€μ μ€μκ° νΌλλ°±μ μ 곡ν©λλ€. μ΄λ¬ν λΌμ΄λΈλ¬λ¦¬λ μ ν¨μ± κ²μ¬ λ
Όλ¦¬λ₯Ό μ²λ¦¬νμ§λ§ useFormStatus
λ μ ν¨μ± κ²μ¬κ° μ€νλλ λμ(λΉλκΈ°μΈ κ²½μ°) λλ μ ν¨μ± κ²μ¬ κ²°κ³Όλ₯Ό κΈ°λ°μΌλ‘ νΌμ΄ μ μΆλκΈ° μ μ λ‘λ© νμκΈ°λ₯Ό νμν μ μμ΅λλ€.
import React from 'react';
import { useFormStatus } from 'react-dom';
import { useFormik } from 'formik'; // Example form library
import * as Yup from 'yup';
function MyForm() {
const { pending } = useFormStatus();
const formik = useFormik({
initialValues: { email: '' },
validationSchema: Yup.object({
email: Yup.string().email('Invalid email address').required('Required'),
}),
onSubmit: async (values) => {
// Simulate an API call
await new Promise(resolve => setTimeout(resolve, 1000));
alert(JSON.stringify(values, null, 2));
},
});
return (
);
}
export default MyForm;
μ΄κ²μ νΌ λΌμ΄λΈλ¬λ¦¬μ μ μΆ μνλ₯Ό ν΅ν©νλ λ°©λ²μ 보μ¬μ€λλ€. `Yup` λ° `formik`μ μ¬μ©νμ¬ νΌ μ ν¨μ± κ²μ¬λ₯Ό ν¬ν¨νμ΅λλ€.
3. μ‘°κ±΄λΆ νΌ μΉμ
νΌ μ μΆ μνμ λ°λΌ νΌ μΉμ μ 쑰건λΆλ‘ λ λλ§ν μ μμ΅λλ€. μλ₯Ό λ€μ΄ μ±κ³΅μ μΈ μ μΆ ν νμΈ νμ΄μ§λ₯Ό νμνκ±°λ μ¬μ©μλ₯Ό 리λλ μ ν©λλ€. μ΄λ κ² νλ©΄ μ¬λ¬ νμ΄μ§λ‘ λΆν λκ±°λ λμ νΌ μ½ν μΈ μ κ°μ΄ μ¬λ¬ λ¨κ³ νΌμ λ§λ€ μ μμ΅λλ€.
useFormStatus
λ₯Ό μ¬μ©ν ν¨κ³Όμ μΈ νΌ κ΄λ¦¬λ₯Ό μν λͺ¨λ² μ¬λ‘
- κ°λ¨νκ² μ μ§: κΈ°λ³Έ ꡬνλΆν° μμνμ¬ νμμ λ°λΌ μ μ°¨μ μΌλ‘ 볡μ‘μ±μ μΆκ°ν©λλ€. μ루μ μ κ³Όλνκ² μμ§λμ΄λ§νμ§ λ§μμμ€.
- λͺ νν μκ°μ μ νΈ: νμ λ‘λ© νμκΈ°, μ±κ³΅ λ©μμ§ λ° μ€λ₯ λ©μμ§μ κ°μ λͺ νν μκ°μ νΌλλ°±μ μ¬μ©μμκ² μ 곡ν©λλ€.
- μ¬μ©μ μΉνμ μΈ μ€λ₯ λ©μμ§: μ¬μ©μμκ² κ΅¬μ²΄μ μ΄κ³ μ€ν κ°λ₯νλ©° μ΄ν΄νκΈ° μ¬μ΄ μ€λ₯ λ©μμ§λ₯Ό μμ±ν©λλ€.
- μ κ·Όμ±: νΌμ΄ μ₯μ κ° μλ μ¬μ©μκ° μ‘μΈμ€ν μ μλμ§ νμΈν©λλ€. ARIA μμ± λ° μλ§¨ν± HTMLμ μ¬μ©ν©λλ€.
- μ² μ ν ν μ€νΈ: λ€μν λΈλΌμ°μ , μ₯μΉ λ° λ€νΈμν¬ μ‘°κ±΄μμ νΌμ ν μ€νΈνμ¬ μ¬λ°λ₯΄κ² μλνλμ§ νμΈν©λλ€. κΈμ μ λ° λΆμ μ ν μ€νΈλ₯Ό λͺ¨λ μ¬μ©ν©λλ€.
- μμ§ μΌμ΄μ€ κ³ λ €: μ μΆ μ€ μΈν°λ· μ°κ²°μ΄ λμ΄μ§κ±°λ μλ²λ₯Ό μ¬μ©ν μ μλ κ²½μ°μ κ°μ μμ§ μΌμ΄μ€μ λν΄ μκ°ν©λλ€. νμν κ²½μ° μ μ ν μ€λ₯ μ²λ¦¬ λ° μ¬μλ λ©μ»€λμ¦μ ꡬνν©λλ€.
- μ΅μ μν μ μ§: μ΅μ React λ° λΈλΌμ°μ κΈ°λ₯μ μ΅μ μνλ‘ μ μ§νμμμ€. νΌ μ²λ¦¬λ₯Ό κ°μ νλ μλ‘μ΄ λ°©λ²μ λμ ν μ μκΈ° λλ¬Έμ λλ€. μλ₯Ό λ€μ΄ μλ‘μ΄ `useTransition` ν μ ν΅ν©νμ¬ μλ΅μ±μ ν₯μμν¬ μ μμ΅λλ€.
κ²°λ‘ : React useFormStatus
λ‘ λ λμ νΌ λ§λ€κΈ°
useFormStatus
ν
μ React μ ν리μΌμ΄μ
μμ νΌ μ μΆ μνλ₯Ό κ΄λ¦¬νλ λ° μ μ©ν λꡬμ
λλ€. μ μΆ μνλ₯Ό μΆμ νλ κΉλνκ³ μ μΈμ μΈ λ°©λ²μ μ 곡ν¨μΌλ‘μ¨ κ°λ°μλ λμ± μ¬μ©μ μΉνμ μ΄κ³ μλ΅μ±μ΄ λ°μ΄λλ©° μ κ·Όμ±μ΄ λ°μ΄λ νΌμ λ§λ€ μ μμ΅λλ€. μ΄ κ°μ΄λλ μ€μ μμ , κΈλ‘λ² λͺ¨λ² μ¬λ‘ λ° κ³ κΈ κΈ°μ μ ν¬ν¨νμ¬ μ μΈκ³ μ¬μ©μλ₯Ό μν΄ κ°λ ₯νκ³ ν¨μ¨μ μΈ νΌμ ꡬμΆνλ λ° λμμ΄ λλ ν
μ λν ν¬κ΄μ μΈ κ°μλ₯Ό μ 곡ν©λλ€.
μ¬μ©μ κ²½νμ μ μ€νκ² κ³ λ €νκ³ λͺ νν μκ°μ μ νΈλ₯Ό ꡬννκ³ ν¨κ³Όμ μΈ μ€λ₯ μ²λ¦¬λ₯Ό ν΅ν©ν¨μΌλ‘μ¨ μ¬μ©νκΈ° νΈλ¦¬νκ³ μ ν리μΌμ΄μ μ μ λ°μ μΈ μ±κ³΅μ κΈ°μ¬νλ νΌμ λ§λ€ μ μμ΅λλ€. μ§ννλ©΄μ κ΅μ ν, νμ§ν λ° μ κ·Όμ±μ λν΄ μκ°νλ κ²μ μμ§ λ§μμμ€. μ΄λ¬ν λ¨κ³λ₯Ό λ°λ₯΄λ©΄ λ λμ νΌμ λ§λ€κ³ μ¬μ©μ κ²½νμ ν₯μμμΌ μ μΈκ³ μ¬μ©μλ₯Ό μν λμ± μ±κ³΅μ μΈ μΉ μ ν리μΌμ΄μ μ λ§λ€ μ μμ΅λλ€.