React 19:useOptimistic Hook

React 19 引入了几个新功能,包括 useOptimistic 钩子。

**useOptimistic** 帮助我们在异步函数进行时更新 UI。

让我们通过一个例子来理解 useOptimistic 的用例

  • 当用户喜欢 Instagram 上的某个帖子时。
  • 客户端(用户设备上的 Instagram 应用程序)将向服务器发出 API 调用以更新点赞数量。(异步操作)
  • 一旦客户端收到服务器的响应,UI 将相应更新以显示正确的点赞数量。
  • 如果服务器速度慢,接收响应和更新 UI 可能会延迟,从而导致用户体验不佳。

    提升用户体验的最佳方式

  • 用户喜欢 Instagram 上的一篇帖子。
  • UI 将立即显示更新的点赞数。
  • 客户端将向服务器发出 API 调用。(异步操作)
  • 如果 API 调用成功,UI 将不会发生变化(因为我们已经显示更新的点赞数)。
  • 如果 API 调用失败,则会删除该赞。
  • 当我们的异步代码(例如本例中的 API 调用)仍在运行时,useOptimistic hook 可以帮助管理喜欢。

    代码

    import { HeartFilledIcon, HeartIcon } from "@radix-ui/react-icons";
    import { Box, Strong, Text } from "@radix-ui/themes";
    import { useOptimistic, useState, useTransition } from "react";
    
    const UseOptimisticExample = () => {
      const [likes, setLikes] = useState(100);
      const [isPostLiked, setIsPostLiked] = useState(false);
      const [optimisticData, setOptimisticData] = useOptimistic(
        { likes, isPostLiked },
        (currentState, newLikes) => {
          return { likes: currentState.likes + newLikes, isPostLiked: true };
        }
      );
      const [, startTransition] = useTransition();
    
      const onLikeClick = () => {
        startTransition(async () => {
          setOptimisticData(1);
          //   Simulating API call
          await new Promise((resolve, reject) => {
            console.log("Request sent to server");
            setTimeout(() => {
              resolve(likes + 1); // To simulate API call success
              //   reject("API call failed"); // To simulate API call failure
            }, 8000);
          })
            .then((newLikes) => {
              console.log("API call success");
              setLikes(newLikes);
              setIsPostLiked(true);
            })
            .catch((error) => {
              console.error(error);
            });
        });
      };
    
      return (
        
          {optimisticData.isPostLiked ? (
            
          ) : (
            
          )}
          

    {optimisticData.likes} Likes
    ); }; export default UseOptimisticExample;