React19 新增Hooks中useOptimistic的使用

 更新时间:2026年05月29日 10:08:02   作者:又双叒叕778  
useOptimistic是React提供的一个Hooks,用于实现乐观更新UI的效果,适用于评论发送等需要即时反馈的场景,下面就来详细的介绍一下

概念

官方文档上介绍:是一个可以帮助你更乐观地更新用户界面 的Hooks,实际上 有点像 loading 的过渡效果,在异步操作的时候先显示一个乐观的结果(即我们提前指定的内容),
如果异步操作成功,再更新成我们预期的内容,如果异步操作失败,那么之前乐观的结果需要被撤销,用户界面要恢复到异步操作开始之前的状态。这样用户界面看起来会更流畅,用户体验更好。

例如,用户在文章下方发表评论,当点击发送按钮时,界面会立即显示为已发送状态,并将评论内容添加到评论列表中,不需要等待服务器的响应,这个时候显示的是一个乐观的结果。如果评论发送成功,那么之前乐观更新的状态会被保留,界面将继续显示为已发送状态,评论内容也会保持在评论列表中。如果评论发送失败,那么之前乐观更新的状态需要被撤销。界面需要回滚到未发送状态,并从评论列表中移除刚才添加的评论内容。

我觉得有一部分有点类似错误边界的感觉,但错误边界 是出现错误之后才显示备用内容,而 useOptimistic 是异步结果返回之前显示乐观内容。

用法

const [optimisticState, addOptimistic] = useOptimistic(
    state,
    // 更新函数
    (currentState, optimisticValue) => {
      // 使用乐观值
      // 合并并返回新 state
    }
  );
  • state:是初始的状态,也就是乐观结果之前的状态
  • updateFn:是更新函数

参数
当前 state (即currentState ) 和传递给 addOptimistic 的值 (即optimisticValue),

返回值
optimisticState:如果异步操作开始或成功,等于currentState 和 optimisticValue 的合并值,其他情况下(不成功或者挂起)都等于state
addOptimistic:触发 optimisticState 更新的函数,通过调用addOptimistic 进而调用内部的 updateFn

效果

useOptimistic Hooks实现效果

//App.js
import { useOptimistic, useState, useRef, startTransition } from "react";

// 模拟异步请求函数
const mockCommentRequest = async (message) => {
  await new Promise((resolve, reject) => {
    setTimeout(() => {
      // 模拟请求成功或失败
      const isSuccess = Math.random() > 0.5;
      if (isSuccess) {
        resolve({ success: true, message: '成功' });
      } else {
        reject({ success: false, message: '失败' });
      }
    }, 1000);
  });
  return message;
};

function Thread({ messages, sendMessageAction }) {
  const formRef = useRef();

  const [optimisticMessages, addOptimisticMessage] = useOptimistic(
    messages,
    (state, newMessage) => {
      // console.log(state, newMessage,'-------------')
      return [
        {
          text: newMessage,
          sending: true
        },
        ...state,
      ]
    }
  );

  function formAction(formData) {
    const message = formData.get("message");
    // 不管异步结果,先进行乐观更新
    addOptimisticMessage(message);
    formRef.current.reset();
    //执行异步操作
    startTransition(async () => {
      await sendMessageAction(message);
    });
  }

  return (
    <>
      <form action={formAction} ref={formRef}>
        <input type="text" name="message" placeholder="发送评论" />
        <button type="submit">发送</button>
      </form>
      {optimisticMessages.map((message, index) => (
        <div key={index}>
          {message.text}
          {message.sending && <small>(发送中……)</small>}
        </div>
      ))}
    </>
  );
}

export default function App() {
  const [messages, setMessages] = useState([
    { text: "评论1", sending: false, key: 1 },
    { text: "评论2", sending: false, key: 2 },
  ]);

  async function sendMessageAction(message) {
    try {
      const sentMessage = await mockCommentRequest(message);
      startTransition(() => {
        setMessages((messages) => [
          { text: sentMessage, sending: false },
          ...messages
        ]);
      });
    } catch (error) {
      console.error('发送失败:', error.message);
      // 可以在这里处理发送失败的情况,例如显示错误提示
    }
  }

  return <Thread messages={messages} sendMessageAction={sendMessageAction} />;
}

思考

1. 在这个Hooks出现之前,我们如何实现类似的效果的呢?

useOptimistic 之前,我们需要手动管理状态来模拟乐观更新和回滚。在实现上,首先把数据添加到显示数组,实现乐观更新,如果异步操作成功,替换成真实发送的消息,如果失败,从显示数组中移除乐观消息,相当于手动回滚到操作前的状态。

function Thread({ messages, sendMessageAction }) {
  const formRef = useRef();
  const [displayMessages, setDisplayMessages] = useState(messages);

  async function formAction(formData) {
    const message = formData.get("message");
    const tempId = Date.now();
    
    // 1. 乐观更新
    setDisplayMessages(prev => [
      { id: tempId, text: message, sending: true },
      ...prev
    ]);
    formRef.current.reset();

    try {
      // 2. 实际发送
      const sentMessage = await sendMessageAction(message);
      
      // 3. 替换乐观消息为实际消息
      setDisplayMessages(prev => [
        { text: sentMessage, sending: false },
        ...prev.filter(msg => msg.id !== tempId)
      ]);
    } catch (error) {
      // 4. 失败时移除乐观消息
      setDisplayMessages(prev => prev.filter(msg => msg.id !== tempId));
      console.error('发送失败:', error.message);
    }
  }

  return (
    <>
      <form action={formAction} ref={formRef}>
        <input type="text" name="message" placeholder="发送评论" />
        <button type="submit">发送</button>
      </form>
      {displayMessages.map((message,index) => (
        <div key={index}>
          {message.text}
          {message.sending && <small>(发送中……)</small>}
        </div>
      ))}
    </>
  );
}

2. useOptimistic 相比于之前的实现 有什么优势吗?

  1. 简化状态管理:可以帮助我们自动回滚到原来的状态,不需要手动回滚
  2. 逻辑分离:把乐观更新的逻辑和异步操作的逻辑分离,使得代码结构更清晰。开发者可以专注于异步操作的实现,而不必过多关注状态管理的细节。

到此这篇关于React19 新增Hooks中useOptimistic的使用的文章就介绍到这了,更多相关React19 新增 useOptimistic内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用react-router4.0实现重定向和404功能的方法

    使用react-router4.0实现重定向和404功能的方法

    本篇文章主要介绍了使用react-router4.0实现重定向和404功能的方法,具有一定的参考价值,有兴趣的可以了解一下
    2017-08-08
  • Native Memory Tracking追踪区域示例分析

    Native Memory Tracking追踪区域示例分析

    这篇文章主要为大家介绍了Native Memory Tracking追踪区域示例分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • 解决React报错Property does not exist on type 'JSX.IntrinsicElements'

    解决React报错Property does not exist on 

    这篇文章主要为大家介绍了React报错Property does not exist on type 'JSX.IntrinsicElements'解决方法,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • React项目中服务器端渲染SSR的实现与优化详解

    React项目中服务器端渲染SSR的实现与优化详解

    在传统的 React 项目里,页面的渲染工作是在浏览器里完成的,而服务器端渲染(SSR)则是让服务器先把 React 组件渲染成 HTML 字符串,再把这个 HTML 字符串发送给浏览器,下面我们就来看看具体实现方法吧
    2025-03-03
  • React 中合成事件的实现示例

    React 中合成事件的实现示例

    本文主要介绍了React 中合成事件的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-02-02
  • React踩坑之antd输入框rules中的required=true问题

    React踩坑之antd输入框rules中的required=true问题

    这篇文章主要介绍了React踩坑之antd输入框rules中的required=true问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • React性能debug场景解决记录

    React性能debug场景解决记录

    这篇文章主要为大家介绍了React性能debug场景解决记录,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • 详解React中传入组件的props改变时更新组件的几种实现方法

    详解React中传入组件的props改变时更新组件的几种实现方法

    这篇文章主要介绍了详解React中传入组件的props改变时更新组件的几种实现方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • React 模式之纯组件使用示例详解

    React 模式之纯组件使用示例详解

    这篇文章主要为大家介绍了React 模式之纯组件使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • React Markdown配置示例

    React Markdown配置示例

    React-Markdown 是一个基于 React 的 Markdown 渲染组件库,其核心设计理念是通过 Unified 生态系统实现安全、可扩展的 Markdown 解析
    2025-04-04

最新评论