Reactã®useOptimisticããã¯ã掻çšããŠãã¬ã¹ãã³ã·ãã§é åçãªãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ãŒã¹ãæ§ç¯ããŸããããå®è·µçãªäŸãšãã¹ããã©ã¯ãã£ã¹ã§æ¥œèгçã¢ããããŒããå®è£ ããæ¹æ³ãåŠã³ãŸãã
React useOptimistic: 楜芳çã¢ããããŒãããã¹ã¿ãŒãã
çŸä»£ã®Webéçºã®äžçã§ã¯ãã·ãŒã ã¬ã¹ã§å¿çæ§ã®é«ããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãæäŸããããšãæéèŠèª²é¡ã§ãããŠãŒã¶ãŒã¯ããããã¯ãŒã¯ãªã¯ãšã¹ãã®ãããªéåææäœãåŠçããŠãããšãã§ããèªåã®ã¢ã¯ã·ã§ã³ã«ã¢ããªã±ãŒã·ã§ã³ãå³åº§ã«åå¿ããããšãæåŸ
ããŠããŸããReactã®useOptimisticããã¯ã¯ããããå®çŸããããã®åŒ·åãªã¡ã«ããºã ãæäŸããUIãããé«éã§å¿çæ§ã®é«ããã®ã«ããæ¥œèгçã¢ããããŒããäœæã§ããŸãã
楜芳çã¢ããããŒããšã¯ïŒ
楜芳çã¢ããããŒããšã¯ã察å¿ãããµãŒããŒåŽã®æäœãå®äºããåã«ãã¢ã¯ã·ã§ã³ã®çµæãåæ ããããã«ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ãŒã¹ãå³åº§ã«æŽæ°ããUIãã¿ãŒã³ã§ããããã«ããããŠãŒã¶ãŒã¯ããã«å€æŽã衚瀺ãããããã峿ãã£ãŒãããã¯ã®é¯èŠãçãŸããŸãããµãŒããŒæäœãæåããå Žåãæ¥œèгçã¢ããããŒãã¯å®éã®ç¶æ ã«ãªããŸãããã ããæäœã倱æããå Žåã¯ã楜芳çã¢ããããŒãã以åã®ç¶æ ã«æ»ãããšã©ãŒãé©åã«åŠçããå¿ èŠããããŸãã
楜芳çã¢ããããŒãããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãå€§å¹ ã«åäžã§ããã·ããªãªãèããŠã¿ãŸãããã
- ã³ã¡ã³ãã®è¿œå : ãŠãŒã¶ãŒãæ°ããã³ã¡ã³ããéä¿¡ããåŸããµãŒããŒãæ£åžžãªä¿åã確èªããã®ãåŸ ããã«ãæ°ããã³ã¡ã³ããããã«è¡šç€ºããŸãã
- æçš¿ãžã®ããã: ãŠãŒã¶ãŒãããããããã¿ã³ãã¯ãªãã¯ãããšãã«ããããæ°ãå³åº§ã«å¢ãããŸãã
- ã¢ã€ãã ã®åé€: ã¢ã€ãã ããªã¹ãããããã«åé€ãã峿ã®èŠèŠçãªãã£ãŒãããã¯ãæäŸããŸãã
- ãã©ãŒã ã®éä¿¡: ãµãŒããŒã§ããŒã¿ãåŠçãããŠããéã§ãããã©ãŒã ãéä¿¡ããåŸããã«æåã¡ãã»ãŒãžã衚瀺ããŸãã
React useOptimisticã®ç޹ä»
React 18ã§å°å
¥ãããReactã®useOptimisticããã¯ã¯ã楜芳çã¢ããããŒãã®å®è£
ãç°¡çŽ åããŸããããã¯ã楜芳çç¶æ
ã管çããæœåšçãªãšã©ãŒãåŠçããããã®ã¯ãªãŒã³ã§å®£èšçãªæ¹æ³ãæäŸããŸãã
æ§æ
useOptimisticããã¯ã¯2ã€ã®åŒæ°ãåããŸãã
const [optimisticState, addOptimistic] = useOptimistic(
initialState,
(currentState, update) => newState
);
initialState: ç¶æ ã®åæå€ã(currentState, update) => newState: çŸåšã®ç¶æ ãšæŽæ°å€ãåŒæ°ãšããŠåãåããæ°ããç¶æ ãè¿ãæŽæ°é¢æ°ããã®é¢æ°ã¯ã楜芳çã¢ããããŒããé©çšããããã³ã«åŒã³åºãããŸãã
ããã¯ã¯æ¬¡ã®ãã®ãå«ãé åãè¿ããŸãã
optimisticState: å®éã®ç¶æ ãšé©çšãããæ¥œèгçã¢ããããŒãã®äž¡æ¹ãå«ãçŸåšã®ç¶æ ãaddOptimistic: æŽæ°å€ãåŒæ°ãšããŠåãåããæ¥œèгçã«ç¶æ ã«é©çšãã颿°ãaddOptimisticã«æž¡ãããåŒæ°ã¯ãæ¬¡ã«æŽæ°é¢æ°ã«æž¡ãããŸãã
å®è·µçãªäŸ: ã³ã¡ã³ãã®è¿œå
å
·äœçãªäŸãšããŠãuseOptimisticã®äœ¿ç𿹿³ã説æããŸããããã°æçš¿ã«ã³ã¡ã³ãã远å ããŸãã
import React, { useState, useOptimistic } from 'react';
function CommentList({ postId, initialComments }) {
const [comments, setComments] = useState(initialComments);
const [optimisticComments, addOptimistic] = useOptimistic(
comments,
(currentComments, newComment) => [...currentComments, newComment]
);
const [isSubmitting, setIsSubmitting] = useState(false);
const handleSubmit = async (event) => {
event.preventDefault();
setIsSubmitting(true);
const text = event.target.elements.comment.value;
const newComment = {
id: `optimistic-${Date.now()}`, // Temporary ID
postId: postId,
text: text,
author: 'You', // Placeholder
createdAt: new Date().toISOString(),
isOptimistic: true // Flag to identify optimistic comments
};
addOptimistic(newComment);
try {
// Simulate an API call to save the comment
await new Promise(resolve => setTimeout(resolve, 1000)); // Simulate network latency
const response = await fetch(`/api/posts/${postId}/comments`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ text })
});
if (!response.ok) {
throw new Error('Failed to save comment');
}
const savedComment = await response.json();
// Replace the optimistic comment with the actual saved comment
setComments(prevComments =>
prevComments.map(comment =>
comment.id === newComment.id ? savedComment : comment
)
);
} catch (error) {
console.error('Error saving comment:', error);
// Revert the optimistic update by filtering out the temporary comment
setComments(prevComments => prevComments.filter(comment => comment.id !== newComment.id));
alert('Failed to save comment. Please try again.'); // Provide user feedback
} finally {
setIsSubmitting(false);
event.target.reset();
}
};
return (
Comments
{optimisticComments.map(comment => (
-
{comment.author} - {comment.text}
{comment.isOptimistic && (Posting...)}
))}
);
}
export default CommentList;
説æ
- åæå: æçš¿ã®æåã®ã³ã¡ã³ãã§
useStateã䜿çšããŠcommentsãåæåããŸããæåã®ã³ã¡ã³ããšæŽæ°é¢æ°ãæž¡ããŠãuseOptimisticã䜿çšããŠoptimisticCommentsãåæåããŸããæŽæ°é¢æ°ã¯ãæ°ããã³ã¡ã³ããæ¢åã®ã³ã¡ã³ãã®ãªã¹ãã«è¿œå ããã ãã§ãã - 楜芳çã¢ããããŒã: ãŠãŒã¶ãŒãã³ã¡ã³ããéä¿¡ãããšãæ°ããã³ã¡ã³ãã
optimisticCommentsç¶æ ã«è¿œå ããaddOptimisticãããã«åŒã³åºããŸããUIã¯ãæ°ããã³ã¡ã³ããããã«è¡šç€ºããããã«æŽæ°ãããŸãããŸããã³ã¡ã³ããæçš¿ãããŠããããšã瀺ãããã«isOptimisticãã©ã°ãèšå®ããŸãã - ãµãŒããŒåŽã®ä¿å: 次ã«ãAPIåŒã³åºãïŒãã®äŸã§ã¯
setTimeoutã§ã·ãã¥ã¬ãŒãïŒãè¡ããã³ã¡ã³ãããµãŒããŒã«ä¿åããŸãã - æåã®åŠç: ãµãŒããŒåŽã®ä¿åãæåããå Žåãä¿åãããã³ã¡ã³ãããµãŒããŒããåãåããŸããæ¬¡ã«ããµãŒããŒã«ãã£ãŠå²ãåœãŠãããIDããã®ä»ã®é¢é£æ
å ±ãå«ããå®éã®ä¿åãããã³ã¡ã³ãã§æ¥œèгçã³ã¡ã³ãã眮ãæããããšã«ãã£ãŠã
commentsã®ç¶æ ãæŽæ°ããŸãã - ãšã©ãŒåŠç: ãµãŒããŒåŽã®ä¿åã倱æããå Žåããšã©ãŒããã£ãããã
commentsç¶æ ããäžæçãªã³ã¡ã³ãããã£ã«ã¿ãªã³ã°ããããšã§ã楜芳çã¢ããããŒããå ã«æ»ããŸãããŸãããŠãŒã¶ãŒã«ãšã©ãŒã¡ãã»ãŒãžã衚瀺ããŸãã - 衚瀺: UIã¯
optimisticCommentsã衚瀺ããŸãã
ããè€éãªã·ããªãªã®åŠç
åã®äŸã¯åçŽãªã·ããªãªã瀺ããŠããŸãã ããè€éãªã·ããªãªã§ã¯ãæ¢åã®ã¢ã€ãã ãžã®æŽæ°ãåé€ããŸãã¯ãã®ä»ã®è€éãªç¶æ
æäœãåŠçããå¿
èŠãããå ŽåããããŸãã éèŠãªã®ã¯ãuseOptimisticã«æž¡ãããæŽæ°é¢æ°ããããã®ã·ããªãªãæ£ããåŠçããããšã§ãã
æ¢åã®ã¢ã€ãã ã®æŽæ°
ãŠãŒã¶ãŒãèªåã®ã³ã¡ã³ããç·šéã§ããããã«ããå ŽåãèããŠã¿ãŸãããã æŽæ°ãããããŒãžã§ã³ã§æ¢åã®ã³ã¡ã³ããæ€çŽ¢ããŠçœ®ãæããããã«æŽæ°é¢æ°ãæŽæ°ããå¿ èŠããããŸãã
const [optimisticComments, addOptimistic] = useOptimistic(
comments,
(currentComments, updatedComment) => {
return currentComments.map(comment => {
if (comment.id === updatedComment.id) {
return updatedComment;
} else {
return comment;
}
});
}
);
ã¢ã€ãã ã®åé€
åæ§ã«ããŠãŒã¶ãŒãã³ã¡ã³ããåé€ã§ããããã«ããå Žåãåé€ãããã³ã¡ã³ãããã£ã«ã¿ãªã³ã°ããããã«æŽæ°é¢æ°ãæŽæ°ããå¿ èŠããããŸãã
const [optimisticComments, addOptimistic] = useOptimistic(
comments,
(currentComments, deletedCommentId) => {
return currentComments.filter(comment => comment.id !== deletedCommentId);
}
);
useOptimisticã䜿çšããããã®ãã¹ããã©ã¯ãã£ã¹
useOptimisticã广çã«æŽ»çšããŠå
ç¢ãªã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããã«ã¯ã次ã®ãã¹ããã©ã¯ãã£ã¹ãæ€èšããŠãã ããã
- 楜芳çã¢ããããŒããèå¥ãã: ç¶æ
ã®æ¥œèгçã¢ããããŒããæç¢ºã«ããŒã¯ããŠïŒããšãã°ã
isOptimisticãã©ã°ã䜿çšïŒãå®éã®ããŒã¿ãšåºå¥ããŸããããã«ãããé©åãªèŠèŠçãªåå³ïŒããšãã°ãããŒãã£ã³ã°ã€ã³ãžã±ãŒã¿ãŒïŒã衚瀺ããæœåšçãªããŒã«ããã¯ãé©åã«åŠçã§ããŸãã - èŠèŠçãªãã£ãŒãããã¯ãæäŸãã: æŽæ°ã楜芳çã§ããã倿Žãããå¯èœæ§ãããããšããŠãŒã¶ãŒã«ç¥ãããŸããããã«ãããæåŸ ã管çããæŽæ°ã倱æããå Žåã®æ··ä¹±ãåé¿ã§ããŸãã埮åŠãªã¢ãã¡ãŒã·ã§ã³ãã¹ã¿ã€ã«ã䜿çšããŠã楜芳çã¢ããããŒããèŠèŠçã«åºå¥ããããšãæ€èšããŠãã ããã
- ãšã©ãŒãé©åã«åŠçãã: ãµãŒããŒæäœã倱æããå Žåã«æ¥œèгçã¢ããããŒããå ã«æ»ãããã«ãå ç¢ãªãšã©ãŒåŠçãå®è£ ããŸãããŠãŒã¶ãŒã«æ å ±ãšã©ãŒã¡ãã»ãŒãžã衚瀺ããæäœãå詊è¡ããããã®ãªãã·ã§ã³ãæäŸããŸãã
- ããŒã¿ã®äžè²«æ§ã確ä¿ãã: ç¹ã«è€éãªããŒã¿æ§é ãŸãã¯è€æ°ã®åææŽæ°ãåŠçããå Žåã¯ãããŒã¿ã®äžè²«æ§ã«çްå¿ã®æ³šæãæã£ãŠãã ããã ç«¶åããæŽæ°ãé²ãããã«ããµãŒããŒåŽã§æ¥œèгçããã¯ãªã©ã®ææ³ãæ€èšããŠãã ããã
- ããã©ãŒãã³ã¹ãæé©åãã: 楜芳çã¢ããããŒãã¯äžè¬çã«ç¥èŠçãªããã©ãŒãã³ã¹ãåäžãããŸãããç¹ã«å€§èŠæš¡ãªããŒã¿ã»ãããåŠçããå Žåã¯ãæœåšçãªããã©ãŒãã³ã¹ããã«ããã¯ã«æ³šæããŠãã ããã ã¡ã¢åãä»®æ³åãªã©ã®ææ³ã䜿çšããŠã¬ã³ããªã³ã°ãæé©åããŸãã
- 培åºçã«ãã¹ããã: æåã倱æãããã³ãšããžã±ãŒã¹ãå«ãããŸããŸãªã·ããªãªã§ã楜芳çã¢ããããŒãã®å®è£ ãæåŸ ã©ããã«åäœããããšã確èªããããã«ã培åºçã«ãã¹ãããŸãã ãããã¯ãŒã¯é å»¶ãšãšã©ãŒãã·ãã¥ã¬ãŒãã§ãããã¹ãã©ã€ãã©ãªã䜿çšããããšãæ€èšããŠãã ããã
ã°ããŒãã«ãªèæ ®äºé
ã°ããŒãã«ã«äœ¿çšãããã¢ããªã±ãŒã·ã§ã³ã§æ¥œèгçã¢ããããŒããå®è£ ããå Žåã¯ã以äžãèæ ®ããŠãã ããã
- ãããã¯ãŒã¯é å»¶: äžçã®ããŸããŸãªå°åã§ããããã¯ãŒã¯é å»¶ãç°ãªããŸããæ¥œèгçã¢ããããŒãã¯ãå¿çæ§ã®é«ããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãæäŸããããã«ãé å»¶ã®é«ãå°åã§ã¯ããã«éèŠã«ãªããŸãã
- ããŒã¿ã®ã¬ãžãã³ã·ãŒãšã³ã³ãã©ã€ã¢ã³ã¹: ããŸããŸãªåœã®ããŒã¿ã®ã¬ãžãã³ã·ãŒãšã³ã³ãã©ã€ã¢ã³ã¹èŠä»¶ã«æ³šæããŠãã ãããæ¥œèгçã¢ããããŒãããããã®èŠä»¶ã«æå³çã«éåããªãããšã確èªããŠãã ãããããšãã°ãããŒã¿ã®ã¬ãžãã³ã·ãŒèŠå¶ã«éåããå Žåã¯ã楜芳çç¶æ ã«æ©å¯ããŒã¿ãä¿åããªãã§ãã ããã
- ããŒã«ãªãŒãŒã·ã§ã³: 楜芳çã¢ããããŒãã«é¢é£ããèŠèŠçãªãã£ãŒãããã¯ãŸãã¯ãšã©ãŒã¡ãã»ãŒãžããããŸããŸãªèšèªãšå°åã«åãããŠé©åã«ããŒã«ã©ã€ãºãããŠããããšã確èªããŠãã ããã
- ã¢ã¯ã»ã·ããªãã£: 楜芳çã¢ããããŒãã瀺ãèŠèŠçãªåå³ããé害ã®ãããŠãŒã¶ãŒã§ãã¢ã¯ã»ã¹ã§ããããã«ããŠãã ãããARIA屿§ãšã»ãã³ãã£ãã¯HTMLã䜿çšããŠãé©åãªã³ã³ããã¹ããšæ å ±ãæäŸããŸãã
- ã¿ã€ã ãŸãŒã³: 楜芳çã¢ããããŒãã«é¢é£ããæ¥ä»ãŸãã¯æå»ãã¢ããªã±ãŒã·ã§ã³ã§è¡šç€ºããå Žåã¯ããŠãŒã¶ãŒã®ããŒã«ã«ã¿ã€ã ãŸãŒã³ã§è¡šç€ºãããŠããããšã確èªããŠãã ããã
useOptimisticã®ä»£æ¿ææ®µ
useOptimisticã¯ã楜芳çã¢ããããŒããå®è£
ããããã®äŸ¿å©ãªæ¹æ³ãæäŸããŸãããå¯äžã®ã¢ãããŒãã§ã¯ãããŸããã ä»ã®ä»£æ¿ææ®µã«ã¯æ¬¡ã®ãããªãã®ããããŸãã
- æåç¶æ
管ç: æšæºã®
useStateããã³useEffectããã¯ã䜿çšããŠã楜芳çã¢ããããŒããå®è£ ã§ããŸãããã®ã¢ãããŒãã§ã¯ãå®è£ ããã现ããå¶åŸ¡ã§ããŸãããããå€ãã®å®åã³ãŒããå¿ èŠã«ãªããŸãã - ç¶æ 管çã©ã€ãã©ãª: ReduxãZustandãJotaiãªã©ã®ã©ã€ãã©ãªã䜿çšããŠã楜芳çã¢ããããŒããå®è£ ããããšãã§ããŸãã ãããã®ã©ã€ãã©ãªã¯ãããæŽç·Žãããç¶æ ç®¡çæ©èœãæäŸããè€éãªã¢ããªã±ãŒã·ã§ã³ã«åœ¹ç«ã¡ãŸãã
- GraphQLã©ã€ãã©ãª: Apollo ClientãRelayãªã©ã®GraphQLã©ã€ãã©ãªã¯ããã£ãã·ã¥ã¡ã«ããºã ãéããŠæ¥œèгçã¢ããããŒãã®çµã¿èŸŒã¿ãµããŒããæäŸããããšããããããŸãã
çµè«
Reactã®useOptimisticããã¯ã¯ãå¿çæ§ã®é«ãé
åçãªãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ãŒã¹ãæ§ç¯ããããã®è²ŽéãªããŒã«ã§ããæ¥œèгçã¢ããããŒããæŽ»çšããããšã§ããŠãŒã¶ãŒã«å³æãã£ãŒãããã¯ãæäŸããããã·ãŒã ã¬ã¹ãªãšã¯ã¹ããªãšã³ã¹ãäœæã§ããŸãã æ¥œèгçã¢ããããŒããå
ç¢ã§å¹æçã§ããããšã確èªããããã«ããšã©ãŒåŠçãããŒã¿ã®äžè²«æ§ãããã³ã°ããŒãã«ãªèæ
®äºé
ãæ³šææ·±ãæ€èšããŠãã ããã
useOptimisticããã¯ããã¹ã¿ãŒããããšã§ãReactã¢ããªã±ãŒã·ã§ã³ã次ã®ã¬ãã«ã«åŒãäžããã°ããŒãã«ãªãªãŒãã£ãšã³ã¹ã«çã«åªãããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãæäŸã§ããŸãã