æ°ããReact experimental_useFormStatusããã¯ã§ãã©ãŒã åŠçã匷åãæ©èœãå©ç¹ããŠãŒã¹ã±ãŒã¹ãå®è£ äŸã解説ããŸãã
React experimental_useFormStatus: å æ¬çã¬ã€ã
é²åãç¶ããReactã®ãšã³ã·ã¹ãã ã¯ãéçºè
äœéšãšã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ãåäžãããããã®æ°ããããŒã«ãAPIãåžžã«å°å
¥ããŠããŸãããã®ãããªè¿œå æ©èœã®äžã€ã§ãçŸåšå®é𿮵éã«ããã®ãexperimental_useFormStatusããã¯ã§ãããã®ããã¯ã¯ãç¹ã«ãµãŒããŒã¢ã¯ã·ã§ã³ãæ±ãéã®ãã©ãŒã éä¿¡ã®ã¹ããŒã¿ã¹ã«é¢ãã貎éãªæŽå¯ãæäŸããŸãããã®ã¬ã€ãã§ã¯ãexperimental_useFormStatusã®è©³çްã«ã€ããŠããã®æ©èœãå©ç¹ãããã³å®è·µçãªå¿çšäŸãæ¢ããŸãã
experimental_useFormStatusãšã¯ïŒ
experimental_useFormStatusããã¯ã¯ãReactãµãŒããŒã¢ã¯ã·ã§ã³ã䜿çšããŠéå§ããããã©ãŒã éä¿¡ã®ç¶æ
ã«é¢ããæ
å ±ãæäŸããããã«èšèšãããŠããŸããããã«ãããã³ã³ããŒãã³ãã¯ä¿çäžãæåã倱æãªã©ããã©ãŒã éä¿¡ããã»ã¹ã®ããŸããŸãªæ®µéã«åå¿ããããšãã§ããŸããããã«ãããéçºè
ã¯ããå¿çæ§ãé«ãããŠãŒã¶ãŒãã¬ã³ããªãŒãªãã©ãŒã äœéšãåµåºã§ããŸãã
æ¬è³ªçã«ããã®ããã¯ã¯ã¯ã©ã€ã¢ã³ããµã€ãã®ãã©ãŒã ãšãµãŒããŒãµã€ãã®ã¢ã¯ã·ã§ã³ãšã®éã®ã®ã£ãããåãããã©ãŒã éä¿¡ã¹ããŒã¿ã¹ã远跡ã衚瀺ããããã®æç¢ºã§ç°¡æœãªæ¹æ³ãæäŸããŸããããã¯ãããŒãã£ã³ã°ã€ã³ãžã±ãŒã¿ãŒãæåã¡ãã»ãŒãžããŸãã¯ãšã©ãŒéç¥ã衚瀺ãããªã©ããŠãŒã¶ãŒã«èŠèŠçãªãã£ãŒãããã¯ãæäŸããã®ã«ç¹ã«åœ¹ç«ã¡ãŸãã
experimental_useFormStatusã䜿çšããäž»ãªå©ç¹
- ãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã®åäž: ãã©ãŒã éä¿¡ç¶æ³ã«é¢ãããªã¢ã«ã¿ã€ã ã®ãã£ãŒãããã¯ãæäŸãããŠãŒã¶ãŒã«æ å ±ãæäŸãããšã³ã²ãŒãžã¡ã³ããç¶æããŸãã
- ãã©ãŒã åŠçã®ç°¡çŽ å: ãã©ãŒã éä¿¡ã®ç®¡çããã»ã¹ãåçåããå®åçãªã³ãŒããåæžããŸãã
- ã¢ã¯ã»ã·ããªãã£ã®åŒ·å: æ¯æŽæè¡ã«äŒéã§ããã¹ããŒã¿ã¹æŽæ°ãæäŸããããšã§ãéçºè ã¯ããã¢ã¯ã»ã·ãã«ãªãã©ãŒã ãäœæã§ããŸãã
- ããè¯ããšã©ãŒãã³ããªã³ã°: ãšã©ãŒã®æ€åºãšå ±åãç°¡çŽ åããããå ç¢ãªãã©ãŒã æ€èšŒãšãšã©ãŒå埩ãå¯èœã«ããŸãã
- ã¯ãªãŒã³ãªã³ãŒã: ãã©ãŒã éä¿¡ã¹ããŒã¿ã¹ã管çããããã®å®£èšçã§ç°¡æœãªæ¹æ³ãæäŸããã³ãŒããèªã¿ããããä¿å®ããããããŸãã
experimental_useFormStatusã®æ§é ãçè§£ãã
experimental_useFormStatusããã¯ã¯ãããã€ãã®äž»èŠãªããããã£ãå«ããªããžã§ã¯ããè¿ããŸãããããã®ããããã£ã¯ããã©ãŒã éä¿¡ã®çŸåšã®ç¶æ
ã«é¢ãã貎éãªæ
å ±ãæäŸããŸããåããããã£ã詳ããèŠãŠãããŸãããïŒ
pending: ãã©ãŒã ã®éä¿¡ãçŸåšé²è¡äžãã©ããã瀺ãããŒã«å€ãããŒãã£ã³ã°ã€ã³ãžã±ãŒã¿ãŒã衚瀺ããã®ã«åœ¹ç«ã¡ãŸããdata: ãã©ãŒã éä¿¡ãæåããéã«ãµãŒããŒã¢ã¯ã·ã§ã³ããè¿ãããããŒã¿ãã¢ã¯ã·ã§ã³ã®çµæã§UIãæŽæ°ããããã«äœ¿çšã§ããŸããerror: ãã©ãŒã éä¿¡äžã«çºçãããšã©ãŒã«é¢ããæ å ±ãå«ããšã©ãŒãªããžã§ã¯ãããŠãŒã¶ãŒã«ãšã©ãŒã¡ãã»ãŒãžã衚瀺ããããã«äœ¿çšã§ããŸããaction: ãã©ãŒã ã®éä¿¡ã«äœ¿çšããããµãŒããŒã¢ã¯ã·ã§ã³é¢æ°ãå¿ èŠã«å¿ããŠã¢ã¯ã·ã§ã³ãåããªã¬ãŒããã®ã«åœ¹ç«ã¡ãŸããformState: éä¿¡åã®ãã©ãŒã ã®ç¶æ ãéä¿¡ããã»ã¹ãéå§ãããåã«ãã©ãŒã ãä¿æããŠããããŒã¿ã®ã¹ãããã·ã§ãããæäŸããŸãã
åºæ¬çãªäœ¿çšäŸ
以äžã¯ãReactã³ã³ããŒãã³ãã§experimental_useFormStatusã䜿çšããåºæ¬çãªäŸã§ãïŒ
import { experimental_useFormStatus as useFormStatus } from 'react-dom';
async function myAction(formData) {
'use server'
// ããã§ãµãŒããŒãµã€ãã®ããžãã¯ãå®è¡
await new Promise(resolve => setTimeout(resolve, 2000)); // é
å»¶ãã·ãã¥ã¬ãŒã
const name = formData.get('name');
if (!name) {
return { message: 'Name is required.' };
}
return { message: `Hello, ${name}!` };
}
function MyForm() {
const { pending, data, error } = useFormStatus();
return (
);
}
export default MyForm;
ãã®äŸã§ã¯ãuseFormStatusãmyActionãµãŒããŒã¢ã¯ã·ã§ã³ã«ãã£ãŠéå§ããããã©ãŒã éä¿¡ã®ã¹ããŒã¿ã¹ã远跡ããããã«äœ¿çšãããŠããŸããpendingããããã£ã¯éä¿¡äžã®å
¥åãšãã¿ã³ãç¡å¹ã«ããããã«äœ¿çšãããdataãšerrorããããã£ã¯ããããæåã¡ãã»ãŒãžãšãšã©ãŒã¡ãã»ãŒãžã衚瀺ããããã«äœ¿çšãããŸãã
é«åºŠãªãŠãŒã¹ã±ãŒã¹
åºæ¬çãªãã©ãŒã éä¿¡ã®è¿œè·¡ä»¥å€ã«ããexperimental_useFormStatusã¯ããé«åºŠãªã·ããªãªã§äœ¿çšã§ããŸãã以äžã«ããã€ãã®äŸã瀺ããŸãïŒ
1. ãªããã£ãã¹ãã£ãã¯æŽæ°ïŒæ¥œèŠ³çæŽæ°ïŒ
ãªããã£ãã¹ãã£ãã¯æŽæ°ãšã¯ãéä¿¡ãæåãããšä»®å®ããŠããŠãŒã¶ãŒããã©ãŒã ãéä¿¡ããçŽåŸã«UIãæŽæ°ããããšã§ããããã«ãããã¢ããªã±ãŒã·ã§ã³ã®äœæããã©ãŒãã³ã¹ãåäžãããããšãã§ããŸããexperimental_useFormStatusã¯ããã©ãŒã éä¿¡ã倱æããå Žåã«ãªããã£ãã¹ãã£ãã¯æŽæ°ãå
ã«æ»ãããã«äœ¿çšã§ããŸãã
import { experimental_useFormStatus as useFormStatus } from 'react-dom';
import { useState } from 'react';
async function updateProfile(formData) {
'use server'
// é
å»¶ãã·ãã¥ã¬ãŒã
await new Promise(resolve => setTimeout(resolve, 2000));
const name = formData.get('name');
if (!name) {
return { success: false, message: 'Name is required.' };
}
return { success: true, message: `Profile updated for ${name}!` };
}
function ProfileForm({ initialName }) {
const { pending, data, error } = useFormStatus();
const [name, setName] = useState(initialName);
const handleSubmit = async (e) => {
e.preventDefault();
// ãªããã£ãã¹ãã£ãã¯æŽæ°
setName(e.target.name.value);
const formData = new FormData(e.target);
const result = await updateProfile(formData);
if (result && !result.success) {
// éä¿¡ã倱æããå Žåã«ãªããã£ãã¹ãã£ãã¯æŽæ°ãå
ã«æ»ã
setName(initialName); // å
ã®å€ã«æ»ã
}
};
return (
);
}
export default ProfileForm;
2. æ¡ä»¶ä»ãã¬ã³ããªã³ã°
experimental_useFormStatusã¯ããã©ãŒã éä¿¡ã®ã¹ããŒã¿ã¹ã«åºã¥ããŠç°ãªãUIèŠçŽ ãæ¡ä»¶ä»ãã§ã¬ã³ããªã³ã°ããããã«äœ¿çšã§ããŸããäŸãã°ããµãŒããŒã¢ã¯ã·ã§ã³ã®æ»ãå€ã«åºã¥ããŠç°ãªãã¡ãã»ãŒãžãUIã衚瀺ããããšãã§ããŸãã
import { experimental_useFormStatus as useFormStatus } from 'react-dom';
async function processOrder(formData) {
'use server'
// é
å»¶ãã·ãã¥ã¬ãŒã
await new Promise(resolve => setTimeout(resolve, 2000));
const orderId = Math.floor(Math.random() * 1000);
return { orderId };
}
function OrderForm() {
const { pending, data, error } = useFormStatus();
return (
);
}
export default OrderForm;
3. ã¢ã¯ã»ã·ããªãã£ã«é¢ããèæ ®äºé
Webéçºã«ãããŠã¢ã¯ã»ã·ããªãã£ã¯æãéèŠã§ããexperimental_useFormStatusã䜿çšãããšããã©ãŒã ã®ã¢ã¯ã»ã·ããªãã£ã倧å¹
ã«åäžãããããšãã§ããŸããäŸãã°ãARIA屿§ã䜿çšããŠã¹ã¯ãªãŒã³ãªãŒããŒã«ãã©ãŒã ã®éä¿¡ã¹ããŒã¿ã¹ãéç¥ããããšãã§ããŸãã
import { experimental_useFormStatus as useFormStatus } from 'react-dom';
async function submitComment(formData) {
'use server'
await new Promise(resolve => setTimeout(resolve, 2000));
const commentText = formData.get('comment');
if (!commentText) {
return { message: 'Comment is required.' };
}
return { message: 'Comment submitted successfully!' };
}
function CommentForm() {
const { pending, data, error } = useFormStatus();
return (
);
}
export default CommentForm;
ãã®ã¹ããããã§ã¯ãaria-busy={pending}ããã©ãŒã éä¿¡äžã§ããããšãæ¯æŽæè¡ã«éç¥ããrole="alert"ãšrole="status"ããããããšã©ãŒã¡ãã»ãŒãžãšæåã¡ãã»ãŒãžãé©åã«ã©ãã«ä»ãããŸãã
ã°ããŒãã«ãªèæ ®äºé ãšãã¹ããã©ã¯ãã£ã¹
experimental_useFormStatusã䜿çšããŠã°ããŒãã«ãªãªãŒãã£ãšã³ã¹åãã®ãã©ãŒã ãéçºããå Žåãã·ãŒã ã¬ã¹ãªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã確ä¿ããããã«ãããã€ãã®èæ
®äºé
ãèæ
®ã«å
¥ããå¿
èŠããããŸãïŒ
- ããŒã«ãªãŒãŒã·ã§ã³: ãã¹ãŠã®ãšã©ãŒã¡ãã»ãŒãžãšæåã¡ãã»ãŒãžããããŸããŸãªèšèªã«é©åã«ããŒã«ã©ã€ãºãããŠããããšã確èªããŠãã ãããããã«ã¯ãã¡ãã»ãŒãžèªäœã®ç¿»èš³ã ãã§ãªããåèšèªã®æ
£ç¿ã«åãããŠã¡ãã»ãŒãžåœ¢åŒãé©å¿ãããããšãå«ãŸããŸãã翻蚳ã管çããããã«ã
i18nextã®ãããªã©ã€ãã©ãªãReactã®çµã¿èŸŒã¿Context APIã®äœ¿çšãæ€èšããŠãã ããã - æ¥ä»ãšæå»ã®åœ¢åŒ: äžçäžã§äœ¿çšãããŠããããŸããŸãªæ¥ä»ãšæå»ã®åœ¢åŒã«æ³šæããŠãã ãããåãã±ãŒã«ã«åãããŠæ¥ä»ãšæå»ãé©åã«ãã©ãŒãããããããã«ã
date-fnsãmoment.jsã®ãããªã©ã€ãã©ãªã䜿çšããŸããäŸãã°ãç±³åœã§ã¯MM/DD/YYYYã䜿çšãããŸãããå€ãã®ãšãŒããã諞åœã§ã¯DD/MM/YYYYã䜿çšãããŸãã - æ°å€åœ¢åŒ: åæ§ã«ãæ°å€åœ¢åŒãå°åã«ãã£ãŠç°ãªããŸãããŠãŒã¶ãŒã®ãã±ãŒã«ã«å¿ããŠæ°å€ããã©ãŒãããããããã«ã
Intl.NumberFormatAPIã䜿çšããŸããããã«ã¯ãå°æ°ç¹åºåãæåãååäœåºåãæåãé貚èšå·ã®åŠçãå«ãŸããŸãã - é貚ã®åãæ±ã: ãã©ãŒã ãéèååŒãå«ãå Žåã¯ãéè²šãæ£ããæ±ã£ãŠããããšã確èªããŠãã ãããæ£ç¢ºãªé貚èšç®ãšå€æãè¡ãããã«ã
currency.jsã®ãããªã©ã€ãã©ãªã䜿çšããŸãã - 倿§ãªãŠãŒã¶ãŒã®ããã®ã¢ã¯ã»ã·ããªãã£: ã¢ã¯ã»ã·ããªãã£ã¬ã€ãã©ã€ã³ã«åŸã£ãŠããã©ãŒã ãé害ãæã€äººã ã«ã䜿çšå¯èœã§ããããšã確èªããŠãã ãããããã«ã¯ãé©åãªARIA屿§ã®æäŸãã»ãã³ãã£ãã¯HTMLã®äœ¿çšããã©ãŒã ãããŒããŒãã§ã¢ã¯ã»ã¹å¯èœã§ããããšã®ç¢ºèªãªã©ãå«ãŸããŸããèŠèŠé害ãèŽèŠé害ãèªç¥ã®éããéåèœåã®å¶éãæã€ãŠãŒã¶ãŒãèæ ®ããŠãã ããã
- ãããã¯ãŒã¯é å»¶: ç¹ã«ã€ã³ã¿ãŒãããæ¥ç¶ãé ãå°åã®ãŠãŒã¶ãŒã®å Žåãæœåšçãªãããã¯ãŒã¯é å»¶ã®åé¡ã«æ³šæããŠãã ãããããŒãã£ã³ã°ã€ã³ãžã±ãŒã¿ãŒãããã°ã¬ã¹ããŒãªã©ããã©ãŒã éä¿¡ããã»ã¹äžã«ãŠãŒã¶ãŒã«æç¢ºãªãã£ãŒãããã¯ãæäŸããŸãã
- ãšã©ãŒã¡ãã»ãŒãžã®æçã: ãŠãŒã¶ãŒã®æåšå°ãæè¡çãªç¿ç床ã«é¢ãããããšã©ãŒã¡ãã»ãŒãžãæç¢ºã§ãç°¡æœã§ãå®è¡å¯èœã§ããããšã確èªããŠãã ãããå°éçšèªã¯é¿ããŠãã ããã
- ããªããŒã·ã§ã³ã«ãŒã«: éµäŸ¿çªå·ã®åœ¢åŒãé»è©±çªå·ã®åœ¢åŒãäœæã®èŠä»¶ãªã©ãããªããŒã·ã§ã³ã«ãŒã«ãããŸããŸãªå°åã®æåŸ ãããæ £ç¿ã«åãããŠããŒã«ã©ã€ãºããŠãã ããã
ãµãŒãããŒãã£ã©ã€ãã©ãªãšã®çµ±å
experimental_useFormStatusã¯ããã©ãŒã åŠçèœåãåäžãããããã«ãããŸããŸãªãµãŒãããŒãã£ã®ãã©ãŒã ã©ã€ãã©ãªãšã·ãŒã ã¬ã¹ã«çµ±åã§ããŸãã以äžã«ããã€ãã®äŸã瀺ããŸãïŒ
- Formik: Formikã¯ããã©ãŒã ã®ç¶æ
管çãšããªããŒã·ã§ã³ãç°¡çŽ åãã人æ°ã®ãã©ãŒã ã©ã€ãã©ãªã§ããFormikãš
experimental_useFormStatusãçµã¿åãããããšã§ããã©ãŒã ã®éä¿¡ã¹ããŒã¿ã¹ãç°¡åã«è¿œè·¡ãããŠãŒã¶ãŒã«ãªã¢ã«ã¿ã€ã ã®ãã£ãŒãããã¯ãæäŸã§ããŸãã - React Hook Form: React Hook Formã¯ãåªããããã©ãŒãã³ã¹ãšæè»æ§ãæäŸãããåºã䜿çšãããŠãããã1ã€ã®ãã©ãŒã ã©ã€ãã©ãªã§ããReact Hook Formãš
experimental_useFormStatusãçµ±åããããšã§ããã©ãŒã ã®éä¿¡ã管çããã¹ããŒã¿ã¹ã®æŽæ°ãã¯ãªãŒã³ã§å¹ççãªæ¹æ³ã§è¡šç€ºã§ããŸãã - Yup: Yupã¯ãå€ã®è§£æãšããªããŒã·ã§ã³ã®ããã®ã¹ããŒããã«ããŒã§ããYupã䜿çšããŠãã©ãŒã ã®ããªããŒã·ã§ã³ã¹ããŒããå®çŸ©ãã
experimental_useFormStatusã䜿çšããŠããªããŒã·ã§ã³ãšã©ãŒããªã¢ã«ã¿ã€ã ã§ãŠãŒã¶ãŒã«è¡šç€ºã§ããŸãã
ãããã®ã©ã€ãã©ãªãšçµ±åããã«ã¯ãã©ã€ãã©ãªã®ãã©ãŒã ã³ã³ããŒãã³ããŸãã¯ãã³ãã©é¢æ°ã«`action`ãããããæž¡ããéä¿¡ã¹ããŒã¿ã¹ã衚瀺ããå¿ èŠãããé¢é£ã³ã³ããŒãã³ãå ã§`experimental_useFormStatus`ã䜿çšããããšãèããããŸãã
代æ¿ã¢ãããŒããšã®æ¯èŒ
experimental_useFormStatusãç»å Žããåã¯ãéçºè
ã¯ãã©ãŒã éä¿¡ã¹ããŒã¿ã¹ã远跡ããããã«ãæåã§ã®ç¶æ
管çãã«ã¹ã¿ã ããã¯ã«äŸåããããšããããããŸããããããã®ã¢ãããŒãã¯é¢åã§ãšã©ãŒãçºçããããå¯èœæ§ããããŸããexperimental_useFormStatusã¯ããã©ãŒã éä¿¡ã管çããããã®ãã宣èšçã§ç°¡æœãªæ¹æ³ãæäŸããå®åçãªã³ãŒããæžãããã³ãŒãã®å¯èªæ§ãåäžãããŸãã
ä»ã®ä»£æ¿æ¡ãšããŠã¯ã`react-query`ã`swr`ã®ãããªã©ã€ãã©ãªã䜿çšããŠãµãŒããŒãµã€ãã®ããŒã¿ãã¥ãŒããŒã·ã§ã³ã管çããããšãèããããŸããããã«ãããæé»çã«ãã©ãŒã éä¿¡ãåŠçã§ããŸããããããexperimental_useFormStatusã¯ãç¹ã«ReactãµãŒããŒã¢ã¯ã·ã§ã³ã䜿çšããå Žåã«ããã©ãŒã ã¹ããŒã¿ã¹ã远跡ããããã®ããçŽæ¥çã§Reactäžå¿ã®æ¹æ³ãæäŸããŸãã
å¶éäºé ãšèæ ®äºé
experimental_useFormStatusã¯å€§ããªå©ç¹ãæäŸããŸããããã®å¶éãšèæ
®äºé
ãèªèããããšãéèŠã§ãïŒ
- å®éšçã¹ããŒã¿ã¹: ãã®ååã瀺ãããã«ã
experimental_useFormStatusã¯ãŸã å®é𿮵éã§ããããã¯ãå°æ¥çã«APIã倿Žãããå¯èœæ§ãããããšãæå³ããŸãã - ãµãŒããŒã¢ã¯ã·ã§ã³ãžã®äŸå: ãã®ããã¯ã¯ReactãµãŒããŒã¢ã¯ã·ã§ã³ãšå¯æ¥ã«çµåããŠããŸããåŸæ¥ã®ã¯ã©ã€ã¢ã³ããµã€ãã®ãã©ãŒã éä¿¡ã§ã¯äœ¿çšã§ããŸããã
- ãã©ãŠã¶äºææ§: ã¿ãŒã²ãããšãããã©ãŠã¶ããReactãµãŒããŒã¢ã¯ã·ã§ã³ãš
experimental_useFormStatusã«å¿ èŠãªæ©èœããµããŒãããŠããããšã確èªããŠãã ããã
çµè«
experimental_useFormStatusããã¯ã¯ãå
ç¢ã§äœ¿ãããããã©ãŒã ãæ§ç¯ããããã®Reactã®ããŒã«ããããžã®è²Žéãªè¿œå æ©èœã§ãããã©ãŒã éä¿¡ã¹ããŒã¿ã¹ã远跡ããããã®å®£èšçã§ç°¡æœãªæ¹æ³ãæäŸããããšã§ããã©ãŒã åŠçãç°¡çŽ åãããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãåäžãããã¢ã¯ã»ã·ããªãã£ã匷åããŸãããŸã å®é𿮵éã§ãããexperimental_useFormStatusã¯Reactã«ããããã©ãŒã éçºã®æªæ¥ã«å€§ããªå¯èœæ§ã瀺ããŠããŸããReactãšã³ã·ã¹ãã ãé²åãç¶ããäžã§ããã®ãããªããŒã«ãåãå
¥ããããšã¯ãçŸä»£çã§ããã©ãŒãã³ã¹ã®é«ãWebã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã«äžå¯æ¬ ã§ãã
experimental_useFormStatusããã®ä»ã®å®éšçæ©èœã«é¢ããææ°æ
å ±ã«ã€ããŠã¯ãåžžã«å
¬åŒã®Reactããã¥ã¡ã³ããåç
§ããããšãå¿ããªãã§ãã ãããããããŒã³ãŒãã£ã³ã°ïŒ