useOptimistic - This feature is available in the latest Canary

Canary

Хук useOptimistic доступен только в React Canary и является экспериментальным. Узнайте больше о релизах React здесь.

useOptimistic — это хук React, который позволяет оптимистично обновлять UI.

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

Справочник

useOptimistic(state, updateFn)

useOptimistic — это хук React, который позволяет показать другое состояние, пока выполняется какое-то асинхронное действие. Он принимает состояние, которое может отличаться во время выполнения асинхронного действия, например, таким действием может быть сетевой запрос. Вы передаёте функцию, которая принимает текущее состояние и входные параметры для какого-то действия, и возвращает оптимистичное состояние, которое используется пока действие находится в режиме ожидания.

This state is called the “optimistic” state because it is usually used to immediately present the user with the result of performing an action, even though the action actually takes time to complete.

import { useOptimistic } from 'react';

function AppContainer() {
const [optimisticState, addOptimistic] = useOptimistic(
state,
// updateFn
(currentState, optimisticValue) => {
// объедините и верните новое состояние
// с оптимистичным значением
}
);
}

Посмотрите больше примеров ниже.

Параметры

  • state: значение, которое вернётся изначально, и во всех случаях, когда нет действий в состоянии ожидания.
  • updateFn(currentState, optimisticValue): функция, которая принимает текущее состояние и оптимистичное значение, переданное в addOptimistic, и возвращает результирующее оптимистичное состояние. Функция должна быть чистой. updateFn принимает два параметра: currentState и optimisticValue. Возвращаемое значение будет результатом объединения currentState и optimisticValue.

Возвращаемое значение

  • optimisticState: Результат оптимистичного состояния. Оно равно state, пока нет действий в состоянии ожидания, иначе будет равно значению, возвращённому из updateFn.
  • addOptimistic: addOptimistic — это функция-диспетчер, которая вызывается при оптимистичном обновлении. Она принимает только один аргумент optimisticValue любого типа и вызовет updateFn с параметрами state and optimisticValue.

Использование

Оптимистичное обновление форм

Хук 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> (Отправка...)</small>}
        </div>
      ))}
      <form action={formAction} ref={formRef}>
        <input type="text" name="message" placeholder="Hello!" />
        <button type="submit">Отправить</button>
      </form>
    </>
  );
}

export default function App() {
  const [messages, setMessages] = useState([
    { text: "Привет!", 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} />;
}