概览useOptimistic 可在提交前立即更新 UI,降低交互延迟感。结合撤销与冲突合并策略,在后台确认失败或产生竞态时稳定回滚或合并,保证一致性与可控性。基础用法'use client'

import { useOptimistic, useState } from 'react'

type Item = { id: string; text: string }

export default function List() {

const [items, setItems] = useState<Item[]>([])

const [optimisticItems, addOptimistic] = useOptimistic(items, (state, pending: Item) => {

return [...state, pending]

})

async function add(text: string) {

const temp: Item = { id: crypto.randomUUID(), text }

addOptimistic(temp)

const ok = await submit(temp)

if (!ok) {

setItems((prev) => prev.filter((i) => i.id !== temp.id))

} else {

setItems((prev) => [...prev, temp])

}

}

return (

<div>

<button onClick={() => add('任务')}>添加</button>

<ul>

{optimisticItems.map((i) => (

<li key={i.id}>{i.text}</li>

))}

</ul>

</div>

)

}

async function submit(i: Item) {

await new Promise((r) => setTimeout(r, 400))

return Math.random() > 0.2

}

撤销与冲突合并'use client'

import { useOptimistic, useRef, useState } from 'react'

type Change = { id: string; text: string }

export function Editor() {

const [base, setBase] = useState<string>('')

const [optimistic, apply] = useOptimistic(base, (state, change: Change) => change.text)

const queue = useRef<Change[]>([])

async function save(next: string) {

const change: Change = { id: crypto.randomUUID(), text: next }

apply(change)

queue.current.push(change)

const ok = await commit(change)

if (!ok) {

// 合并策略:回退到最新成功版本

const last = queue.current.at(-2)

setBase(last ? last.text : base)

} else {

setBase(next)

}

}

return (

<div>

<textarea defaultValue={base} onBlur={(e) => save(e.target.value)} />

<p>预览:{optimistic}</p>

</div>

)

}

async function commit(c: Change) {

await new Promise((r) => setTimeout(r, 500))

return true

}

治理要点对失败场景提供撤销或回滚保障,避免状态撕裂。合并策略以最新成功提交为基线,减少竞态污染。与 Server Actions 协作,将幂等与去重纳入后端保障。验证与指标React:19.0+;Next.js:15.0+即时反馈:按钮与文本在 100–200ms 内出现乐观更新;失败可在 1s 内回滚

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部