Reactμ useFormState ν μ μ¬μ©νμ¬ κ°λ ₯νκ³ νμ₯ κ°λ₯ν λ€λ¨κ³ νΌ μ ν¨μ± κ²μ¬ νμ΄νλΌμΈμ ꡬννλ λ°©λ²μ λ°°μλλ€. μ΄ κ°μ΄λμμλ κΈ°λ³Έ μ ν¨μ± κ²μ¬λΆν° κ³ κΈ λΉλκΈ° μλ리μ€κΉμ§ λͺ¨λ κ²μ λ€λ£Ήλλ€.
React useFormState μ ν¨μ± κ²μ¬ νμ΄νλΌμΈ: λ€λ¨κ³ νΌ μ ν¨μ± κ²μ¬ λ§μ€ν°νκΈ°
κ°λ ₯ν μ ν¨μ± κ²μ¬λ₯Ό μ¬μ©νλ 볡μ‘ν νΌμ ꡬμΆνλ κ²μ μ΅μ μΉ κ°λ°μμ νν λ¬Έμ μ
λλ€. Reactμ useFormState ν
μ μ κ΅ν λ€λ¨κ³ μ ν¨μ± κ²μ¬ νμ΄νλΌμΈ μμ±μ κ°λ₯νκ² νμ¬ νΌ μν λ° μ ν¨μ± κ²μ¬λ₯Ό κ΄λ¦¬νλ κ°λ ₯νκ³ μ μ°ν λ°©λ²μ μ 곡ν©λλ€. μ΄ ν¬κ΄μ μΈ κ°μ΄λλ κΈ°λ³Έ μ¬νμ μ΄ν΄νλ κ²λΆν° κ³ κΈ λΉλκΈ° μ ν¨μ± κ²μ¬ μ λ΅μ ꡬννλ κ²κΉμ§ νλ‘μΈμ€λ₯Ό μλ΄ν©λλ€.
λ€λ¨κ³ νΌ μ ν¨μ± κ²μ¬κ° νμν μ΄μ ?
κΈ°μ‘΄μ λ¨μΌ λ¨κ³ νΌ μ ν¨μ± κ²μ¬λ νΉν λ§μ νλλ 볡μ‘ν μ’ μμ±μ΄ ν¬ν¨λ νΌμ μ²λ¦¬ν λ λ²κ±°λ‘κ³ λΉν¨μ¨μ μΌ μ μμ΅λλ€. λ€λ¨κ³ μ ν¨μ± κ²μ¬λ₯Ό ν΅ν΄ λ€μμ μνν μ μμ΅λλ€.
- μ¬μ©μ κ²½ν κ°μ : νΉμ νΌ μΉμ μ λν μ¦κ°μ μΈ νΌλλ°±μ μ 곡νμ¬ μ¬μ©μκ° μλ£ νλ‘μΈμ€λ₯Ό λ³΄λ€ ν¨κ³Όμ μΌλ‘ μλ΄ν©λλ€.
- μ±λ₯ ν₯μ: μ 체 νΌμ λν λΆνμν μ ν¨μ± κ²μ¬ νμΈμ λ°©μ§νμ¬ νΉν λκ·λͺ¨ νΌμ μ±λ₯μ μ΅μ νν©λλ€.
- μ½λ μ μ§ κ΄λ¦¬μ± ν₯μ: μ ν¨μ± κ²μ¬ λ Όλ¦¬λ₯Ό λ μκ³ κ΄λ¦¬νκΈ° μ¬μ΄ λ¨μλ‘ λΆν νμ¬ μ½λλ₯Ό λ μ½κ² μ΄ν΄νκ³ ν μ€νΈνκ³ μ μ§ κ΄λ¦¬ν μ μμ΅λλ€.
useFormState μ΄ν΄
useFormState ν
(μΌλ°μ μΌλ‘ react-useμ κ°μ λΌμ΄λΈλ¬λ¦¬ λλ μ¬μ©μ μ μ ꡬνμμ μ¬μ© κ°λ₯)μ νΌ μν, μ ν¨μ± κ²μ¬ μ€λ₯ λ° μ μΆ μ²λ¦¬λ₯Ό κ΄λ¦¬νλ λ°©λ²μ μ 곡ν©λλ€. ν΅μ¬ κΈ°λ₯μ λ€μκ³Ό κ°μ΅λλ€.
- μν κ΄λ¦¬: νΌ νλμ νμ¬ κ°μ μ μ₯ν©λλ€.
- μ ν¨μ± κ²μ¬: νΌ κ°μ λν μ ν¨μ± κ²μ¬ κ·μΉμ μ€νν©λλ€.
- μ€λ₯ μΆμ : κ° νλμ κ΄λ ¨λ μ ν¨μ± κ²μ¬ μ€λ₯λ₯Ό μΆμ ν©λλ€.
- μ μΆ μ²λ¦¬: νΌμ μ μΆνκ³ μ μΆ κ²°κ³Όλ₯Ό μ²λ¦¬νλ λ©μ»€λμ¦μ μ 곡ν©λλ€.
κΈ°λ³Έ μ ν¨μ± κ²μ¬ νμ΄νλΌμΈ ꡬμΆ
κ°μΈ μ 보(μ΄λ¦, μ΄λ©μΌ) λ° μ£Όμ μ 보(거리, λμ, κ΅κ°)μ λ λ¨κ³ νΌμ κ°λ¨ν μμ λ‘ μμνκ² μ΅λλ€.
1λ¨κ³: νΌ μν μ μ
λ¨Όμ λͺ¨λ νλλ₯Ό ν¬ν¨νμ¬ νΌμ μ΄κΈ° μνλ₯Ό μ μν©λλ€.
const initialFormState = {
firstName: '',
lastName: '',
email: '',
street: '',
city: '',
country: '',
};
2λ¨κ³: μ ν¨μ± κ²μ¬ κ·μΉ λ§λ€κΈ°
λ€μμΌλ‘ μ ν¨μ± κ²μ¬ κ·μΉμ μ μν©λλ€. μ΄ μμμλ λͺ¨λ νλκ° λΉμ΄ μμ§ μμμΌ νκ³ μ΄λ©μΌμ΄ μ ν¨ν νμμ΄μ΄μΌ ν©λλ€.
const validateField = (fieldName, value) => {
if (!value) {
return 'νμ μ
λ ₯ νλͺ©μ
λλ€.';
}
if (fieldName === 'email' && !/^\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(value)) {
return 'μ ν¨νμ§ μμ μ΄λ©μΌ νμμ
λλ€.';
}
return null; // μ€λ₯ μμ
};
3λ¨κ³: useFormState ν
ꡬν
μ΄μ (κ°μμ) useFormState ν
μ μ¬μ©νμ¬ μ ν¨μ± κ²μ¬ κ·μΉμ React μ»΄ν¬λνΈμ ν΅ν©ν΄ λ³΄κ² μ΅λλ€.
import React, { useState } from 'react';
// μ¬μ©μ μ μ ꡬν λλ react-useμ κ°μ λΌμ΄λΈλ¬λ¦¬ κ°μ
const useFormState = (initialState) => {
const [values, setValues] = useState(initialState);
const [errors, setErrors] = useState({});
const handleChange = (event) => {
const { name, value } = event.target;
setValues({ ...values, [name]: value });
// λ λμ UXλ₯Ό μν΄ λ³κ²½ μ μ ν¨μ± κ²μ¬(μ ν μ¬ν)
setErrors({ ...errors, [name]: validateField(name, value) });
};
const validateFormStage = (fields) => {
const newErrors = {};
let isValid = true;
fields.forEach(field => {
const error = validateField(field, values[field]);
if (error) {
newErrors[field] = error;
isValid = false;
}
});
setErrors({...errors, ...newErrors}); //κΈ°μ‘΄ μ€λ₯μ λ³ν©
return isValid;
};
const clearErrors = (fields) => {
const newErrors = {...errors};
fields.forEach(field => delete newErrors[field]);
setErrors(newErrors);
};
return {
values,
errors,
handleChange,
validateFormStage,
clearErrors,
};
};
const MyForm = () => {
const { values, errors, handleChange, validateFormStage, clearErrors } = useFormState(initialFormState);
const [currentStage, setCurrentStage] = useState(1);
const handleNextStage = () => {
let isValid;
if (currentStage === 1) {
isValid = validateFormStage(['firstName', 'lastName', 'email']);
} else {
isValid = validateFormStage(['street', 'city', 'country']);
}
if (isValid) {
setCurrentStage(currentStage + 1);
}
};
const handlePreviousStage = () => {
if(currentStage > 1){
if(currentStage === 2){
clearErrors(['firstName', 'lastName', 'email']);
} else {
clearErrors(['street', 'city', 'country']);
}
setCurrentStage(currentStage - 1);
}
};
const handleSubmit = (event) => {
event.preventDefault();
const isValid = validateFormStage(['firstName', 'lastName', 'email', 'street', 'city', 'country']);
if (isValid) {
// νΌ μ μΆ
console.log('νΌ μ μΆλ¨:', values);
alert('νΌμ΄ μ μΆλμμ΅λλ€!'); //μ€μ μ μΆ λ
Όλ¦¬λ‘ λ체
} else {
console.log('νΌμ μ€λ₯κ° μμ΅λλ€. μμ νμμμ€.');
}
};
return (
);
};
export default MyForm;
4λ¨κ³: λ¨κ³ νμ ꡬν
μν λ³μλ₯Ό μ¬μ©νμ¬ νΌμ νμ¬ λ¨κ³λ₯Ό κ΄λ¦¬νκ³ νμ¬ λ¨κ³λ₯Ό κΈ°λ°μΌλ‘ μ μ ν νΌ μΉμ μ λ λλ§ν©λλ€.
κ³ κΈ μ ν¨μ± κ²μ¬ κΈ°μ
λΉλκΈ° μ ν¨μ± κ²μ¬
κ²½μ°μ λ°λΌ μ ν¨μ± κ²μ¬μλ μ¬μ©μ μ΄λ¦μ΄ μ¬μ© κ°λ₯νμ§ νμΈνλ κ²κ³Ό κ°μ΄ μλ²μμ μνΈ μμ©μ΄ νμν©λλ€. μ΄λ₯Ό μν΄μλ λΉλκΈ° μ ν¨μ± κ²μ¬κ° νμν©λλ€. ν΅ν© λ°©λ²μ λ€μκ³Ό κ°μ΅λλ€.
const validateUsername = async (username) => {
try {
const response = await fetch(`/api/check-username?username=${username}`);
const data = await response.json();
if (data.available) {
return null; // μ¬μ©μ μ΄λ¦μ μ¬μ©ν μ μμ΅λλ€.
} else {
return 'μ¬μ©μ μ΄λ¦μ΄ μ΄λ―Έ μ¬μ© μ€μ
λλ€.';
}
} catch (error) {
console.error('μ¬μ©μ μ΄λ¦ νμΈ μ€λ₯:', error);
return 'μ¬μ©μ μ΄λ¦ νμΈ μ€λ₯μ
λλ€. λ€μ μλνμμμ€.'; // λ€νΈμν¬ μ€λ₯λ₯Ό μ μμ μΌλ‘ μ²λ¦¬ν©λλ€.
}
};
const useFormStateAsync = (initialState) => {
const [values, setValues] = useState(initialState);
const [errors, setErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
const handleChange = (event) => {
const { name, value } = event.target;
setValues({ ...values, [name]: value });
};
const validateFieldAsync = async (fieldName, value) => {
if (fieldName === 'username') {
return await validateUsername(value);
}
return validateField(fieldName, value);
};
const handleSubmit = async (event) => {
event.preventDefault();
setIsSubmitting(true);
let newErrors = {};
let isValid = true;
for(const key in values){
const error = await validateFieldAsync(key, values[key]);
if(error){
newErrors[key] = error;
isValid = false;
}
}
setErrors(newErrors);
setIsSubmitting(false);
if (isValid) {
// νΌ μ μΆ
console.log('νΌ μ μΆλ¨:', values);
alert('νΌμ΄ μ μΆλμμ΅λλ€!'); //μ€μ μ μΆ λ
Όλ¦¬λ‘ λ체
} else {
console.log('νΌμ μ€λ₯κ° μμ΅λλ€. μμ νμμμ€.');
}
};
return {
values,
errors,
handleChange,
handleSubmit,
isSubmitting //μ ν μ¬ν: μ ν¨μ± κ²μ¬ μ€μ λ‘λ© λ©μμ§ νμ
};
};
μ΄ μμ μλ μ¬μ©μ μ΄λ¦ κ°μ©μ±μ νμΈνκΈ° μν΄ API νΈμΆμ μννλ validateUsername ν¨μκ° ν΅ν©λμ΄ μμ΅λλ€. μ μ¬μ μΈ λ€νΈμν¬ μ€λ₯λ₯Ό μ²λ¦¬νκ³ μ¬μ©μμκ² μ μ ν νΌλλ°±μ μ 곡νμμμ€.
μ‘°κ±΄λΆ μ ν¨μ± κ²μ¬
μΌλΆ νλλ λ€λ₯Έ νλμ κ°μ λ°λΌ μ ν¨μ± κ²μ¬κ° νμν μ μμ΅λλ€. μλ₯Ό λ€μ΄ μ¬μ©μκ° κ³ μ© μνμμ λνλ΄λ κ²½μ° "νμ¬ μΉμ¬μ΄νΈ" νλλ§ νμμΌ μ μμ΅λλ€. μ ν¨μ± κ²μ¬ ν¨μ λ΄μμ μ‘°κ±΄λΆ μ ν¨μ± κ²μ¬λ₯Ό ꡬνν©λλ€.
const validateFieldConditional = (fieldName, value, formValues) => {
if (fieldName === 'companyWebsite' && formValues.employmentStatus === 'employed' && !value) {
return 'κ³ μ© μνμΈ κ²½μ° νμ¬ μΉμ¬μ΄νΈλ νμμ
λλ€.';
}
return validateField(fieldName, value); // κΈ°λ³Έ μ ν¨μ± κ²μ¬μ μμ
};
λμ μ ν¨μ± κ²μ¬ κ·μΉ
κ²½μ°μ λ°λΌ μ ν¨μ± κ²μ¬ κ·μΉ μμ²΄κ° μΈλΆ μμΈμ΄λ λ°μ΄ν°λ₯Ό κΈ°λ°μΌλ‘ λμ μ΄μ΄μΌ ν©λλ€. μ ν¨μ± κ²μ¬ κ·μΉμ μ ν¨μ± κ²μ¬ ν¨μμ μΈμλ‘ μ λ¬νμ¬ μ΄λ₯Ό λ¬μ±ν μ μμ΅λλ€.
const validateFieldWithDynamicRules = (fieldName, value, rules) => {
if (rules && rules[fieldName] && rules[fieldName].maxLength && value.length > rules[fieldName].maxLength) {
return `μ΄ νλλ ${rules[fieldName].maxLength}μ λ―Έλ§μ΄μ΄μΌ ν©λλ€.`
}
return validateField(fieldName, value); // κΈ°λ³Έ μ ν¨μ± κ²μ¬μ μμ
};
μ€λ₯ μ²λ¦¬ λ° μ¬μ©μ κ²½ν
κΈμ μ μΈ μ¬μ©μ κ²½νμ μν΄μλ ν¨κ³Όμ μΈ μ€λ₯ μ²λ¦¬κ° μ€μν©λλ€. λ€μ μ¬νμ κ³ λ €νμμμ€.
- μ€λ₯λ₯Ό λͺ ννκ² νμ: ν΄λΉ μ λ ₯ νλ κ·Όμ²μ μ€λ₯ λ©μμ§λ₯Ό λ°°μΉν©λλ€. λͺ ννκ³ κ°κ²°ν μΈμ΄λ₯Ό μ¬μ©ν©λλ€.
- μ€μκ° μ ν¨μ± κ²μ¬: μ¬μ©μκ° μ λ ₯ν λ νλμ μ ν¨μ±μ κ²μ¬νμ¬ μ¦κ°μ μΈ νΌλλ°±μ μ 곡ν©λλ€. μ±λ₯μ λ―ΈμΉλ μν₯μ μ μνμμμ€. νμν κ²½μ° μ ν¨μ± κ²μ¬ νΈμΆμ λλ°μ΄μ€νκ±°λ μ€λ‘νλ§ν©λλ€.
- μ€λ₯μ μ§μ€: μ μΆ ν μ€λ₯κ° μλ 첫 λ²μ§Έ νλμ μ¬μ©μμ μ£Όμλ₯Ό μ§μ€ν©λλ€.
- μ κ·Όμ±: ARIA μμ± λ° μλ―Έ μ²΄κ³ HTMLμ μ¬μ©νμ¬ μ€λ₯ λ©μμ§κ° μ₯μ κ° μλ μ¬μ©μμκ² μ κ·Ό κ°λ₯νμ§ νμΈν©λλ€.
- κ΅μ ν(i18n): μ μ ν κ΅μ νλ₯Ό ꡬννμ¬ μ¬μ©μκ° μ νΈνλ μΈμ΄λ‘ μ€λ₯ λ©μμ§λ₯Ό νμν©λλ€. i18next λλ λ€μ΄ν°λΈ JavaScript Intl APIμ κ°μ μλΉμ€λ₯Ό μ¬μ©ν μ μμ΅λλ€.
λ€λ¨κ³ νΌ μ ν¨μ± κ²μ¬λ₯Ό μν λͺ¨λ² μ¬λ‘
- μ ν¨μ± κ²μ¬ κ·μΉμ κ°κ²°νκ² μ μ§: 볡μ‘ν μ ν¨μ± κ²μ¬ λ Όλ¦¬λ₯Ό λ μκ³ μ¬μ¬μ© κ°λ₯ν ν¨μλ‘ λλλλ€.
- μ² μ ν ν μ€νΈ: μ ν¨μ± κ²μ¬ κ·μΉμ μ νμ±κ³Ό μ λ’°μ±μ 보μ₯νκΈ° μν΄ λ¨μ ν μ€νΈλ₯Ό μμ±ν©λλ€.
- μ ν¨μ± κ²μ¬ λΌμ΄λΈλ¬λ¦¬ μ¬μ©: νλ‘μΈμ€λ₯Ό λ¨μννκ³ μ½λ νμ§μ κ°μ νκΈ° μν΄ μ μ© μ ν¨μ± κ²μ¬ λΌμ΄λΈλ¬λ¦¬(μ: Yup, Zod)λ₯Ό μ¬μ©νλ κ²μ΄ μ’μ΅λλ€. μ΄λ¬ν λΌμ΄λΈλ¬λ¦¬λ μ’ μ’ μ€ν€λ§ κΈ°λ° μ ν¨μ± κ²μ¬λ₯Ό μ 곡νμ¬ λ³΅μ‘ν μ ν¨μ± κ²μ¬ κ·μΉμ λ μ½κ² μ μνκ³ κ΄λ¦¬ν μ μμ΅λλ€.
- μ±λ₯ μ΅μ ν: νΉν μ€μκ° μ ν¨μ± κ²μ¬ μ€μ λΆνμν μ ν¨μ± κ²μ¬ νμΈμ νΌν©λλ€. λ©λͺ¨μ΄μ μ΄μ κΈ°μ μ μ¬μ©νμ¬ μ ν¨μ± κ²μ¬ κ²°κ³Όλ₯Ό μΊμ±ν©λλ€.
- λͺ νν μ§μΉ¨ μ 곡: λͺ νν μ§μΉ¨κ³Ό μ μ©ν ννΈλ₯Ό ν΅ν΄ μ¬μ©μκ° νΌ μλ£ νλ‘μΈμ€λ₯Ό μλ΄ν©λλ€.
- μ μ§μ κ³΅κ° κ³ λ €: κ° λ¨κ³μ λν κ΄λ ¨ νλλ§ νμνμ¬ νΌμ λ¨μννκ³ μΈμ§ λΆνλ₯Ό μ€μ λλ€.
λ체 λΌμ΄λΈλ¬λ¦¬ λ° μ κ·Ό λ°©μ
μ΄ κ°μ΄λμμλ μ¬μ©μ μ μ useFormState ν
μ μ€μ μ λκ³ μμ§λ§ μ μ¬ν κΈ°λ₯μ μ 곡νλ μ¬λ¬ κ°μ§ νλ₯ν νΌ λΌμ΄λΈλ¬λ¦¬κ° μμΌλ©° μ’
μ’
μΆκ° κΈ°λ₯κ³Ό μ±λ₯ μ΅μ νκ° ν¨κ» μ 곡λ©λλ€. λͺ κ°μ§ μΈκΈ° μλ λμμ λ€μκ³Ό κ°μ΅λλ€.
- Formik: Reactμμ νΌ μν λ° μ ν¨μ± κ²μ¬λ₯Ό κ΄λ¦¬νλ λ° λ리 μ¬μ©λλ λΌμ΄λΈλ¬λ¦¬μ λλ€. νΌ μ²λ¦¬μ λν μ μΈμ μ κ·Ό λ°©μμ μ 곡νκ³ λ€μν μ ν¨μ± κ²μ¬ μ λ΅μ μ§μν©λλ€.
- React Hook Form: μ μ΄λμ§ μλ μ»΄ν¬λνΈμ Reactμ ref APIλ₯Ό νμ©νμ¬ λ€μ λ λλ§μ μ΅μννλ μ±λ₯ μ€μ¬ λΌμ΄λΈλ¬λ¦¬μ λλ€. ν¬κ³ 볡μ‘ν νΌμ νμν μ±λ₯μ μ 곡ν©λλ€.
- Final Form: λ€μν UI νλ μμν¬ λ° μ ν¨μ± κ²μ¬ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ§μνλ λ€μ©λ λΌμ΄λΈλ¬λ¦¬μ λλ€. νΌ λμμ μ¬μ©μ μ μνκΈ° μν μ μ°νκ³ νμ₯ κ°λ₯ν APIλ₯Ό μ 곡ν©λλ€.
μ¬λ°λ₯Έ λΌμ΄λΈλ¬λ¦¬ μ νμ νΉμ μꡬ μ¬νκ³Ό μ νΈλμ λ°λΌ λ€λ¦ λλ€. κ²°μ μ λ΄λ¦΄ λ μ±λ₯, μ¬μ© νΈμμ± λ° κΈ°λ₯ μΈνΈμ κ°μ μμλ₯Ό κ³ λ €νμμμ€.
κ΅μ μ κ³ λ € μ¬ν
κΈλ‘λ² μ¬μ©μλ₯Ό μν νΌμ ꡬμΆν λλ κ΅μ ν λ° νμ§νλ₯Ό κ³ λ €νλ κ²μ΄ νμμ μ λλ€. λͺ κ°μ§ μ£Όμ μΈ‘λ©΄μ λ€μκ³Ό κ°μ΅λλ€.
- λ μ§ λ° μκ° νμ: μΌκ΄μ±μ 보μ₯νκ³ νΌλμ νΌνκΈ° μν΄ λ‘μΊλ³ λ μ§ λ° μκ° νμμ μ¬μ©ν©λλ€.
- μ«μ νμ: ν΅ν κΈ°νΈ λ° μμμ κ΅¬λΆ κΈ°νΈλ₯Ό ν¬ν¨νμ¬ λ‘μΊλ³ μ«μ νμμ μ¬μ©ν©λλ€.
- μ£Όμ νμ: μ£Όμ νλλ₯Ό λ€μν κ΅κ° νμμ λ§κ² μ‘°μ ν©λλ€. μΌλΆ κ΅κ°μμλ λμ μμ μ°νΈ λ²νΈκ° νμν μ μκ³ , λ€λ₯Έ κ΅κ°μμλ μ°νΈ λ²νΈκ° μ ν μμ μ μμ΅λλ€.
- μ ν λ²νΈ μ ν¨μ± κ²μ¬: κ΅μ μ ν λ²νΈ νμμ μ§μνλ μ ν λ²νΈ μ ν¨μ± κ²μ¬ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©ν©λλ€.
- λ¬Έμ μΈμ½λ©: νΌμ΄ μ λμ½λ λ° κΈ°ν λΉλΌν΄ λ¬Έμλ₯Ό ν¬ν¨νμ¬ λ€μν λ¬Έμ μ§ν©μ μ¬λ°λ₯΄κ² μ²λ¦¬νλμ§ νμΈν©λλ€.
- μ€λ₯Έμͺ½μμ μΌμͺ½(RTL) λ μ΄μμ: κ·Έμ λ°λΌ νΌ λ μ΄μμμ μ‘°μ νμ¬ μλμ΄ λ° νλΈλ¦¬μ΄μ κ°μ RTL μΈμ΄λ₯Ό μ§μν©λλ€.
μ΄λ¬ν κ΅μ μ μΈ‘λ©΄μ κ³ λ €ν¨μΌλ‘μ¨ κΈλ‘λ² μ¬μ©μκ° μ κ·Όνκ³ μ¬μ©νκΈ° μ¬μ΄ νΌμ λ§λ€ μ μμ΅λλ€.
κ²°λ‘
Reactμ useFormState ν
(λλ λ체 λΌμ΄λΈλ¬λ¦¬)μ μ¬μ©νμ¬ λ€λ¨κ³ νΌ μ ν¨μ± κ²μ¬ νμ΄νλΌμΈμ ꡬννλ©΄ μ¬μ©μ κ²½νμ ν¬κ² κ°μ νκ³ μ±λ₯μ ν₯μμν€λ©° μ½λ μ μ§ κ΄λ¦¬μ±μ λμΌ μ μμ΅λλ€. ν΅μ¬ κ°λ
μ μ΄ν΄νκ³ μ΄ κ°μ΄λμ μ€λͺ
λ λͺ¨λ² μ¬λ‘λ₯Ό μ μ©νλ©΄ μ΅μ μΉ μ ν리μΌμ΄μ
μ μꡬ μ¬νμ μΆ©μ‘±νλ κ°λ ₯νκ³ νμ₯ κ°λ₯ν νΌμ ꡬμΆν μ μμ΅λλ€.
μ¬μ©μ κ²½νμ μ°μ μνκ³ μ² μ ν ν μ€νΈνκ³ νλ‘μ νΈμ νΉμ μꡬ μ¬νμ λ§κ² μ ν¨μ± κ²μ¬ μ λ΅μ μ‘°μ νλ κ²μ μμ§ λ§μμμ€. μ μ€ν κ³νκ³Ό μ€νμ ν΅ν΄ κΈ°λ₯μ μ΄κ³ μ¬μ©νκΈ° μ¦κ±°μ΄ νΌμ λ§λ€ μ μμ΅λλ€.