useOptimistic

useOptimistic 是一个 React Hook,允许你乐观地更新 UI。

const [optimisticState, addOptimistic] = useOptimistic(state, updateFn);

参考

useOptimistic(state, updateFn)

useOptimistic 是一个 React Hook,允许你在异步操作进行时显示不同的状态。它接受一些状态作为参数,并在异步操作(例如网络请求)期间返回该状态的一个副本,该副本可能不同。你提供一个函数,该函数接受当前状态和操作的输入,并返回在操作挂起期间使用的乐观状态。

这种状态被称为“乐观”状态,因为它通常用于立即向用户呈现执行操作的结果,即使操作实际上需要时间才能完成。

import { useOptimistic } from 'react';

function AppContainer() {
const [optimisticState, addOptimistic] = useOptimistic(
state,
// updateFn
(currentState, optimisticValue) => {
// merge and return new state
// with optimistic value
}
);
}

请参见下面的更多示例。

参数

  • state:最初返回的值,以及任何操作未挂起时的值。
  • updateFn(currentState, optimisticValue):一个函数,它接受当前状态和传递给 addOptimistic 的乐观值,并返回生成的乐观状态。它必须是一个纯函数。updateFn 接受两个参数:currentStateoptimisticValue。返回值将是 currentStateoptimisticValue 的合并值。

返回值

  • optimisticState:生成的乐观状态。除非操作正在挂起,否则它等于 state,在这种情况下,它等于 updateFn 返回的值。
  • addOptimistic: addOptimistic 是在进行乐观更新时调用的分发函数。它接收一个参数 optimisticValue(任何类型),并将使用 stateoptimisticValue 调用 updateFn

用法

乐观更新表单

useOptimistic 钩子提供了一种在后台操作(例如网络请求)完成之前乐观更新用户界面的方法。在表单的上下文中,此技术有助于使应用程序感觉更具响应性。当用户提交表单时,界面会立即使用预期结果进行更新,而不是等待服务器的响应来反映更改。

例如,当用户在表单中键入消息并点击“发送”按钮时,useOptimistic 钩子允许消息立即出现在列表中,并带有“正在发送...”标签,即使消息实际上尚未发送到服务器。这种“乐观”的方法给人以速度和响应迅速的印象。然后,表单尝试在后台真正发送消息。一旦服务器确认已收到消息,“正在发送...”标签就会被移除。

import { useOptimistic, useState, useRef } from "react";
import { deliverMessage } from "./actions.js";

function Thread({ messages, sendMessage }) {
  const formRef = useRef();
  async function formAction(formData) {
    addOptimisticMessage(formData.get("message"));
    formRef.current.reset();
    await sendMessage(formData);
  }
  const [optimisticMessages, addOptimisticMessage] = useOptimistic(
    messages,
    (state, newMessage) => [
      ...state,
      {
        text: newMessage,
        sending: true
      }
    ]
  );

  return (
    <>
      {optimisticMessages.map((message, index) => (
        <div key={index}>
          {message.text}
          {!!message.sending && <small> (Sending...)</small>}
        </div>
      ))}
      <form action={formAction} ref={formRef}>
        <input type="text" name="message" placeholder="Hello!" />
        <button type="submit">Send</button>
      </form>
    </>
  );
}

export default function App() {
  const [messages, setMessages] = useState([
    { text: "Hello there!", sending: false, key: 1 }
  ]);
  async function sendMessage(formData) {
    const sentMessage = await deliverMessage(formData.get("message"));
    setMessages((messages) => [...messages, { text: sentMessage }]);
  }
  return <Thread messages={messages} sendMessage={sendMessage} />;
}