useOptimistic 是 React19 提供了一个新的 hooks,他可以实现乐观更新,使得数据更新效果更加友好。

乐观更新:在进行服务器请求接口时,先在用户界面上预先处理成功的结果(假设操作成功),然后再发送请求到服务器进行确认。如果服务器返回错误,前端再进行相应的回滚或错误处理。

useOptimistic 的语法

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

useOptimistic 接收两个参数:

  • state:初始状态
  • updateFn:一个函数,接收当前状态和乐观更新值,返回新一个和当前状态和新值合并的新状态。

useOptimistic 返回值:

  • optimisticState:是 updateFn 返回的新状态 optimisticState
  • addOptimisticaddOptimistic 是需要乐观更新时要调用的函数。它接受一个状态,会传递给 updateFn 的第二个参数,返回新状态 optimisticValue

上述的描述可能有点抽象,我们进行场景模拟来解释下该 hook 的使用。

举个例子

我们直接举一个实际应用的例子来看,现在要实现一个评论列表,每次新增评论时,会立刻把结果显示在列表中,并同步到服务器,但是,如果服务器返回错误,则进行回滚提示。我们先来创建一个 App 组件。

App组件

export default function App() {
const [comments, setComments] = useState([{ text: "第一条评论", sending: false }]);
async function addComment(formData) {
const newComment = await postComment(formData.get("comment"));
setComments((comments) => [...comments, { text: newComment }]);
}
return <CommentSection comments={comments} addComment={addComment} />;
}

CommentSection组件

我们要实现一个评论组件,包含列表展示功能和评论表单提交功能。

function CommentSection({ comments, addComment }) {
const formRef = useRef();
const [optimisticComments, addOptimisticComment] = useOptimistic(comments, (state, newComment) => [
...state,
{
text: newComment,
sending: true,
failed: false,
},
]);
async function handleFormSubmit(formData) {
const newComment = formData.get("comment");
addOptimisticComment(newComment); // 乐观更新
formRef.current.reset();
try {
await addComment(formData);
} catch (error) {
handleFailure(newComment);
}
}
function handleFailure(failedComment) {
// 提示失败
}
return (
<>
<div>
{optimisticComments.map((comment, index) => (
<div key={index} style={{ color: comment.failed ? "red" : "black" }}>
{comment.text}
{!!comment.sending && <small> (发送中...)</small>}
</div>
))}
</div>
<form action={handleFormSubmit} ref={formRef}>
<input type="text" name="comment" placeholder="评论..." />
<button type="submit">提交</button>
</form>
</>
);
}

最终效果