Reactã®useOptimisticããã¯ã䜿çšããŠã楜芳çã¢ããããŒãã«ãããããã¹ã ãŒãºã§ã¬ã¹ãã³ã¹ã®è¯ããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãå®çŸããæ¹æ³ãåŠã³ãŸããå®è·µçãªäŸãšãã¹ããã©ã¯ãã£ã¹ãæ¢æ±ããŸãã
React useOptimistic: 楜芳çã¢ããããŒãã®å æ¬çãªã¬ã€ã
ãŠã§ãéçºã®äžçã§ã¯ãã¬ã¹ãã³ã¹ãè¯ããé
åçãªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãäœæããããšãæãéèŠã§ãããããå®çŸããããã®éèŠãªææ³ã®1ã€ã¯ã楜芳çã¢ããããŒãã§ããReact 18ã§å°å
¥ãããReactã®useOptimistic
ããã¯ã¯ããã®ãã¿ãŒã³ãå®è£
ããããã®åçåãããæ¹æ³ãæäŸããŸãããã®ã¬ã€ãã§ã¯ãuseOptimistic
ã®è©³çްãæãäžãããã®å©ç¹ããŠãŒã¹ã±ãŒã¹ãããã³ãã¹ããã©ã¯ãã£ã¹ãæ¢æ±ããŸãã
楜芳çã¢ããããŒããšã¯äœã§ããïŒ
楜芳çã¢ããããŒããšã¯ãéåææäœïŒãµãŒããŒãžã®ãããã¯ãŒã¯ãªã¯ãšã¹ããªã©ïŒãæåãããšä»®å®ããŠããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ãŒã¹ïŒUIïŒãæŽæ°ããããšãæå³ããŸããå®éã«ã¯ãµãŒããŒãã確èªãåãåãåã«è¡ãããŸããããã«ãããå³åº§ã«ãã£ãŒãããã¯ãåŸããããšããé¯èŠãçãããŠãŒã¶ãŒã®ã¬ã¹ãã³ã¹ã«å¯Ÿããèªèãå€§å¹ ã«åäžããŸããæäœãåŸã§å€±æããå ŽåãUIã¯å ã®ç¶æ ã«æ»ããŸãã
ãŠãŒã¶ãŒãæçš¿ã«ããããïŒãã§ãããœãŒã·ã£ã«ã¡ãã£ã¢ã¢ããªã±ãŒã·ã§ã³ãèããŠã¿ãŸããããæ¥œèгçã¢ããããŒãããªãå ŽåããããïŒãã¿ã³ãã¯ãªãã¯ãããšããµãŒããŒãžã®ãªã¯ãšã¹ããããªã¬ãŒãããŸããæ¬¡ã«ããµãŒããŒããããïŒã確èªãããŸã§ãUIã«ããŒãã£ã³ã°ç¶æ ïŒäŸïŒã¹ãããŒïŒã衚瀺ãããŸããããã¯ãç¹ã«ã¬ã€ãã³ã·ãŒã®é«ããããã¯ãŒã¯ã§ã¯ãé ããŠæ±ãã«ãããšæããããå¯èœæ§ããããŸãã
楜芳çã¢ããããŒãã䜿çšãããšããŠãŒã¶ãŒããã¿ã³ãã¯ãªãã¯ãããšãUIã¯ããã«æŽæ°ãããŠæçš¿ãæ°ã«å ¥ã£ãããã«è¡šç€ºãããŸãããµãŒããŒãžã®ãªã¯ãšã¹ãã¯åŒãç¶ãããã¯ã°ã©ãŠã³ãã§è¡ãããŸãããªã¯ãšã¹ããæåããå Žåãäœã倿ŽãããŸããããã ãããªã¯ãšã¹ãã倱æããå ŽåïŒäŸïŒãããã¯ãŒã¯ãšã©ãŒãŸãã¯ãµãŒããŒã®åé¡ãåå ïŒãUIã¯å ã®ç¶æ ã«æ»ãããŠãŒã¶ãŒã«ãšã©ãŒã¡ãã»ãŒãžã衚瀺ãããå ŽåããããŸãã
楜芳çã¢ããããŒãã®å©ç¹
- ãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã®åäžïŒæ¥œèгçã¢ããããŒãã«ãããã¢ããªã±ãŒã·ã§ã³ã®åäœãããéããããã¬ã¹ãã³ã¹ãè¯ããªããããæºè¶³ã®ãããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã«ã€ãªãããŸãã
- ç¥èŠãããã¬ã€ãã³ã·ãŒã®åæžïŒUIãããã«æŽæ°ããããšã§ããããã¯ãŒã¯ãªã¯ãšã¹ãããã®ä»ã®éåææäœã«é¢é£ããã¬ã€ãã³ã·ãŒãé èœããŸãã
- ãŠãŒã¶ãŒãšã³ã²ãŒãžã¡ã³ãã®åäžïŒã¬ã¹ãã³ã¹ã®è¯ãUIã¯ããŠãŒã¶ãŒãã¢ããªã±ãŒã·ã§ã³ãšããå€ã察話ããããšã奚å±ããŸãã
useOptimistic
ã®ç޹ä»
useOptimistic
ããã¯ã¯ãReactã§ã®æ¥œèгçã¢ããããŒãã®å®è£
ãç°¡çŽ åããŸããããã«ã¯ã次ã®2ã€ã®åŒæ°ãå¿
èŠã§ãã
- åæç¶æ ïŒæ¥œèгçã«æŽæ°ããç¶æ ã®åæå€ã
- æŽæ°é¢æ°ïŒçŸåšã®ç¶æ ãšæ¥œèгçã¢ããããŒãå€ãå ¥åãšããŠåãåããæ¥œèгçã¢ããããŒããé©çšããåŸã®æ°ããç¶æ ãè¿ã颿°ã
ãã®ããã¯ã¯ã以äžãå«ãé åãè¿ããŸãã
- çŸåšã®ç¶æ ïŒããã¯æ¥œèгçã¢ããããŒããåæ ããç¶æ ã§ãã
- 楜芳çã¢ããããŒããé©çšãã颿°ïŒãã®é¢æ°ã¯ã楜芳çã¢ããããŒãå€ãå ¥åãšããŠåãåããæŽæ°ãããç¶æ ã§åã¬ã³ããªã³ã°ãããªã¬ãŒããŸãã
åºæ¬çãªäŸïŒæçš¿ã«ãããïŒãã
ãœãŒã·ã£ã«ã¡ãã£ã¢ã®äŸã«æ»ã£ãŠãuseOptimistic
ã䜿çšããŠæ¥œèгçãªãããïŒãå®è£
ããæ¹æ³ãèŠãŠã¿ãŸãããã
import React, { useState, useOptimistic } from 'react';
function Post({ postId, initialLikes }) {
const [isLiking, setIsLiking] = useState(false);
const [optimisticLikes, addOptimisticLike] = useOptimistic(
initialLikes,
(state, optimisticUpdate) => state + optimisticUpdate
);
const handleLike = async () => {
setIsLiking(true);
addOptimisticLike(1);
try {
// Simulate an API call to like the post
await new Promise((resolve) => setTimeout(resolve, 500)); // Simulate network latency
// await api.likePost(postId); // Replace with your actual API call
} catch (error) {
console.error("Failed to like post:", error);
addOptimisticLike(-1); // Revert the optimistic update
// Optionally, display an error message to the user
} finally {
setIsLiking(false);
}
};
return (
<div>
<p>Likes: {optimisticLikes}</p>
<button onClick={handleLike} disabled={isLiking}>
{isLiking ? "Liking..." : "Like"}
</button>
</div>
);
}
export default Post;
説æïŒ
useOptimistic
ãæçš¿ã®initialLikes
æ°ã§åæåããŸãã- æŽæ°é¢æ°ã¯ã
optimisticUpdate
ïŒ1ãŸãã¯-1ã«ãªããŸãïŒãçŸåšã®state
ïŒãããïŒã®æ°ïŒã«è¿œå ããã ãã§ãã - ãŠãŒã¶ãŒããããïŒãã¿ã³ãã¯ãªãã¯ãããšã
addOptimisticLike(1)
ãåŒã³åºããŠãUIã®ãããïŒæ°ãããã«å¢ãããŸãã - 次ã«ããµãŒããŒäžã§æçš¿ã«ãããïŒããããã«APIåŒã³åºããè¡ããŸãïŒãã®äŸã§ã¯
setTimeout
ã§ã·ãã¥ã¬ãŒããããŠããŸãïŒã - APIåŒã³åºããæåããå Žåãäœãèµ·ãããŸãããUIã¯æ¥œèгçãªãããïŒã§æŽæ°ããããŸãŸã«ãªããŸãã
- APIåŒã³åºãã倱æããå Žåã
addOptimisticLike(-1)
ãåŒã³åºããŠæ¥œèгçã¢ããããŒããå ã«æ»ãããŠãŒã¶ãŒã«ãšã©ãŒã¡ãã»ãŒãžã衚瀺ããŸãã
é«åºŠãªäŸïŒã³ã¡ã³ãã远å ãã
楜芳çã¢ããããŒãã¯ãã³ã¡ã³ãã®è¿œå ãªã©ãããè€éãªæäœã«ã䜿çšã§ããŸãããã®æ¹æ³ãèŠãŠã¿ãŸãããã
import React, { useState, useOptimistic } from 'react';
function CommentSection({ postId, initialComments }) {
const [newCommentText, setNewCommentText] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);
const [optimisticComments, addOptimisticComment] = useOptimistic(
initialComments,
(state, optimisticComment) => [...state, optimisticComment]
);
const handleAddComment = async (e) => {
e.preventDefault();
if (!newCommentText.trim()) return;
setIsSubmitting(true);
const optimisticComment = { id: Date.now(), text: newCommentText, author: 'You (Optimistic)' };
addOptimisticComment(optimisticComment);
setNewCommentText('');
try {
// Simulate an API call to add the comment
await new Promise((resolve) => setTimeout(resolve, 500)); // Simulate network latency
// const newComment = await api.addComment(postId, newCommentText); // Replace with your actual API call
// In a real implementation, you'd replace the optimistic comment with the actual comment
// addOptimisticComment(newComment) // Example:
} catch (error) {
console.error("Failed to add comment:", error);
// Revert the optimistic update (remove the last comment)
addOptimisticComment(null); // Use a special value to signal removal.
//optimisticComments.pop(); // This will not trigger a re-render
// Optionally, display an error message to the user
} finally {
setIsSubmitting(false);
}
};
return (
<div>
<h3>Comments</h3>
<ul>
{optimisticComments.map((comment) => (
comment ? <li key={comment.id}>{comment.text} - {comment.author}</li> :
null // Render nothing if null comment. Handle cases where comment addition failed
))}
</ul>
<form onSubmit={handleAddComment}>
<input
type="text"
value={newCommentText}
onChange={(e) => setNewCommentText(e.target.value)}
placeholder="Add a comment..."
disabled={isSubmitting}
/>
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Submitting..." : "Add Comment"}
</button>
</form>
</div>
);
}
export default CommentSection;
説æïŒ
useOptimistic
ãinitialComments
é åã§åæåããŸãã- æŽæ°é¢æ°ã¯ã
optimisticComment
ãstate
ïŒã³ã¡ã³ãã®é åïŒã«è¿œå ããŸãã - ãŠãŒã¶ãŒãæ°ããã³ã¡ã³ããéä¿¡ãããšãäžæçãªIDãšãŠãŒã¶ãŒã®å
¥åãå«ã
optimisticComment
ãªããžã§ã¯ããäœæããŸãã addOptimisticComment(optimisticComment)
ãåŒã³åºããŠã楜芳çãªã³ã¡ã³ããUIã«ããã«è¿œå ããŸãã- 次ã«ãAPIåŒã³åºãïŒ
setTimeout
ã§ã·ãã¥ã¬ãŒãïŒãè¡ãããµãŒããŒã«ã³ã¡ã³ãã远å ããŸãã - APIåŒã³åºããæåããå Žåãå®éã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãäžæçãªã³ã¡ã³ããæ£ããã³ã¡ã³ãïŒéä¿¡åŸã«åä¿¡ããã³ã¡ã³ãïŒã«çœ®ãæããŸãã
- APIåŒã³åºãã倱æããå Žåã
addOptimisticComment(null)
ãåŒã³åºããŠæåŸã®ã³ã¡ã³ãïŒæ¥œèгçãªã³ã¡ã³ãã ã£ããã®ïŒãåé€ããå ã®ç¶æ ã«æ»ããŸãã - ã³ã¡ã³ãã®è¿œå ã«å€±æããå ŽåïŒ
comment ? <li ...> : null
ïŒãåŠçããŸã
useOptimistic
ã䜿çšããããã®ãã¹ããã©ã¯ãã£ã¹
- ãšã©ãŒãé©åã«åŠçããïŒéåææäœã«åžžã«ãšã©ãŒåŠçãå«ããŠãå¿ èŠã«å¿ããŠæ¥œèгçã¢ããããŒããå ã«æ»ããŸãããŠãŒã¶ãŒã«æçãªãšã©ãŒã¡ãã»ãŒãžã衚瀺ããŸãã
- èŠèŠçãªãã£ãŒãããã¯ãæäŸããïŒæ¥œèгçã¢ããããŒããé²è¡äžã®å ŽåããŠãŒã¶ãŒã«æç¢ºã«ç€ºããŸããããã¯ãèæ¯è²ãå€ãããããŒãã£ã³ã°ã€ã³ãžã±ãŒã¿ãŒã衚瀺ãããªã©ã埮åŠãªèŠèŠçåå³ã§ãããŸããŸããã
- ãããã¯ãŒã¯é å»¶ãèæ ®ããïŒãããã¯ãŒã¯é å»¶ã«æ³šæããŠãã ãããé å»¶ãåžžã«å€§ããå Žåãæ¥œèгçã¢ããããŒãã¯ããã»ã©å¹æçã§ã¯ãªãå¯èœæ§ããããŸããããŒã¿ã®ããªãã§ãããªã©ãä»£æ¿æŠç¥ãæ€èšããŠãã ããã
- é©åãªããŒã¿æ§é ã䜿çšããïŒæŽæ°ãšå ã«æ»ãã®ã«å¹ççãªããŒã¿æ§é ãéžæããŸããããšãã°ãã€ãã¥ãŒã¿ãã«ãªããŒã¿æ§é ã䜿çšãããšãå ã®ç¶æ ã«æ»ãããã»ã¹ãç°¡çŽ åã§ããŸãã
- ã¢ããããŒããããŒã«ã©ã€ãºããïŒæ¥œèгçã¢ããããŒãããæäœã®åœ±é¿ãåããç¹å®ã®UIèŠçŽ ã«ã®ã¿é©çšããŸããUIå šäœãäžå¿ èŠã«æŽæ°ããããšã¯é¿ããŠãã ããã
- ãšããžã±ãŒã¹ãæ€èšããïŒåæã¢ããããŒããç«¶åããããŒã¿ãªã©ãæœåšçãªãšããžã±ãŒã¹ã«ã€ããŠèããŠãã ããããããã®ç¶æ³ãåŠçããããã®é©åãªæŠç¥ãå®è£ ããŸãã
- ãŠãŒã¶ãŒå ¥åããããŠã³ã¹ãŸãã¯ã¹ãããã«ããïŒãŠãŒã¶ãŒãããŒã¿ãæ¥éã«å ¥åããŠããå ŽåïŒäŸïŒæ€çŽ¢ããã¯ã¹ã«å ¥åããŠããå ŽåïŒããããŠã³ã¹ãã¹ãããã«ãªã©ã®ææ³ã䜿çšããŠã楜芳çã¢ããããŒãã®é »åºŠãå¶éãããµãŒããŒã«éè² è·ããããªãããã«ããããšãæ€èšããŠãã ããã
- ãã£ãã·ã¥ãšãšãã«äœ¿çšããïŒãã£ãã·ã¥ã¡ã«ããºã ãšçµã¿åãããŠã楜芳çã¢ããããŒãã¯ã·ãŒã ã¬ã¹ãªãšã¯ã¹ããªãšã³ã¹ãæäŸã§ããŸããUIãšãšãã«ãã£ãã·ã¥ã楜芳çã«æŽæ°ãããµãŒããŒããŒã¿ãå°çããã調æŽããŸãã
- é床ã®äœ¿çšãé¿ããïŒæ¥œèгçã¢ããããŒãã¯æŠç¥çã«äœ¿çšããŸããé床ã«äœ¿çšãããšãã¢ããããŒããé »ç¹ã«å€±æããå Žåã«æ··ä¹±ãæãå¯èœæ§ããããŸããèªèãããå¿çæ§ãéèŠãªå¯Ÿè©±ã«çŠç¹ãåœãŠãŠãã ããã
useOptimistic
ã«é¢ããã°ããŒãã«ãªèæ
®äºé
ã°ããŒãã«ãªãªãŒãã£ãšã³ã¹åãã®ã¢ããªã±ãŒã·ã§ã³ãéçºããå Žåã¯ã次ã®ãããªèŠçŽ ãèæ ®ããããšãéèŠã§ãã
- ãããã¯ãŒã¯ã®ç¶æ ïŒãããã¯ãŒã¯ã®ç¶æ ã¯ãå°åã«ãã£ãŠå€§ããç°ãªãå ŽåããããŸããæ¥œèгçã¢ããããŒãã¯ãä¿¡é Œæ§ã®äœãããŸãã¯äœéã®ã€ã³ã¿ãŒãããæ¥ç¶ã®å°åã§ç¹ã«åœ¹ç«ã¡ãŸãã
- ããŒã«ãªãŒãŒã·ã§ã³ïŒãšã©ãŒã¡ãã»ãŒãžããã®ä»ã®UIèŠçŽ ããããŸããŸãªèšèªãå°åã«åãããŠé©åã«ããŒã«ã©ã€ãºãããŠããããšã確èªããŸãã
- ã¢ã¯ã»ã·ããªãã£ïŒã¢ããªã±ãŒã·ã§ã³ãé害ã®ãããŠãŒã¶ãŒã«ãšã£ãŠã¢ã¯ã»ã¹å¯èœã§ããããšã確èªããŸããæ¥œèгçã¢ããããŒããæ¯æŽæè¡ãšäºææ§ããªãå Žåã¯ãUIãšå¯Ÿè©±ããããã®ä»£æ¿æ¹æ³ãæäŸããŸãã
- ããŒã¿äž»æš©ïŒããŸããŸãªåœã®ããŒã¿äž»æš©èŠå¶ã«æ³šæããŠãã ãããããŒã¿ãããŒã«ã«æ³ã«æºæ ããŠåŠçããã³ä¿åãããããã«ããŸãã
- ã¿ã€ã ãŸãŒã³ïŒæ¥ä»ãšæå»ã衚瀺ããå Žåã¯ãã¿ã€ã ãŸãŒã³ãèæ ®ããŠãã ãããæ¥œèгçã¢ããããŒãã§ã¯ã衚瀺ãããæ å ±ããŠãŒã¶ãŒã®å Žæã«å¯ŸããŠæ£ç¢ºã§ããããšã確èªããããã«èª¿æŽãå¿ èŠã«ãªãå ŽåããããŸããããšãã°ãäºå®ã楜芳çã«äœæãããå Žåãéç¥ããŠãŒã¶ãŒã®ã¿ã€ã ãŸãŒã³ã§è¡šç€ºãããããã«ããŸãã
useOptimistic
ã®ä»£æ¿æ¡
useOptimistic
ã¯æ¥œèгçã¢ããããŒããå®è£
ããããã®äŸ¿å©ãªæ¹æ³ã§ããã代æ¿ã¢ãããŒãããããŸãã
- æåç¶æ
管çïŒReactã®
useState
ããã³useEffect
ããã¯ã䜿çšããŠã楜芳çã¢ããããŒããæåã§å®è£ ã§ããŸããããã«ãããã¢ããããŒãããã»ã¹ããã现ããå¶åŸ¡ã§ããŸãããããå€ãã®ã³ãŒããå¿ èŠã«ãªããŸãã - ç¶æ 管çã©ã€ãã©ãªïŒReduxãZustandãªã©ã®ã©ã€ãã©ãªã䜿çšããŠãã¢ããªã±ãŒã·ã§ã³ã®ç¶æ ã管çããæ¥œèгçã¢ããããŒããå®è£ ã§ããŸãããããã®ã©ã€ãã©ãªã¯ãè€éãªç¶æ é·ç§»ã管çããããã®ããé«åºŠãªæ©èœãæäŸããŸãã
- GraphQLã©ã€ãã©ãªïŒApollo ClientãRelayãªã©ã®ã©ã€ãã©ãªã¯ãGraphQL APIã䜿çšããå Žåã«æ¥œèгçã¢ããããŒãã®çµã¿èŸŒã¿ãµããŒããæäŸããŸãã
çµè«
Reactã®useOptimistic
ããã¯ã¯ãããå¿çæ§ãé«ãé
åçãªãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ãŒã¹ãäœæããããã®åŒ·åãªããŒã«ã§ããæ¥œèгçã¢ããããŒãã®ååãçè§£ãããã¹ããã©ã¯ãã£ã¹ã«åŸãããšã§ãReactã¢ããªã±ãŒã·ã§ã³ã®ãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã倧å¹
ã«åäžãããããšãã§ããŸãããœãŒã·ã£ã«ã¡ãã£ã¢ãã©ãããã©ãŒã ãeã³ããŒã¹ãŠã§ããµã€ãããŸãã¯å
±åäœæ¥ããŒã«ãæ§ç¯ããŠããå Žåã§ããæ¥œèгçã¢ããããŒãã¯ãäžçäžã®ãŠãŒã¶ãŒã«ãšã£ãŠããã¹ã ãŒãºã§æ¥œãããšã¯ã¹ããªãšã³ã¹ãäœæããã®ã«åœ¹ç«ã¡ãŸãã倿§ãªãªãŒãã£ãšã³ã¹ã«æ¥œèгçã¢ããããŒããå®è£
ããå Žåã¯ããããã¯ãŒã¯ã®ç¶æ
ãããŒã«ãªãŒãŒã·ã§ã³ãã¢ã¯ã»ã·ããªãã£ãªã©ã®ã°ããŒãã«ãªèŠå ãèæ
®ããããšãå¿ããªãã§ãã ããã