useOptimisitc
useOptimistic
允许在异步操作进行的时候展示不同的状态,它接受两个参数,一个是用来初始化所要展示的状态,另一个是一个函数,用来在操作挂起期间展示乐观状态使用。
乐观状态 Hook 的常见使用格式如下:
const [optimisticState, addOptimistic] = useOptimistic(
initialState,
(currentState, optimisitcValue) => {
return newState;
}
);
useOptimistic
通常用来立刻向用户展示动作执行结果,即便是这个所需要执行的动作需要一段时间才能够完成。
这里借用官网上的示例来说明useOptimistic
要如何来使用。
async function expensiveDeliverMessage(message: string) {
await new Promise((resolve) => setTimeout(resolve, 3000));
return message;
}
const Thread = ({ messages, sendMessage }) => {
const formRef = useRef();
const [optimisticMessages, addOptimisticMessage] = useOptimistic(
messages,
(currentState, newMessage) => [
...currentState,
{ text: newMessage, sending: true },
]
);
const formAction = async (formData) => {
addOptimisticMessage(formData.get("message"));
formRef.current.reset();
await sendMessage(formData);
};
return (
<>
{optimisticMessages.map((message, index) => (
<div key={index}>
{message.text}
{!!message.sending && <span>(Sending..)</span>}
</div>
))}
<form action={formAction} ref={formRef}>
<input type="text" name="message" />
<button type="submit">Send</button>
</form>
</>
);
};
const App = () => {
const [messages, setMessages] = useState([]);
const sendMessage = async (formData) => {
const messageSent = await expensiveDeliverMessage(formData.get("message"));
setMessages((prev) => [...prev, { text: messageSent }]);
};
return <Thread messages={messages} sendMessage={sendMessage} />;
};
在这个示例中,组件<Thread>
展示的messages
内容实际上是从上一级<App>
组件中传递来的,而messages
的变化也是在<App>
中完成的。如果不使用useOptimistic
的话,在点击<Thread>
组件的提交按钮以后,需要等待一段时间,才能够看到刚刚添加的内容在列表里刷新出来。
但是在<Thread>
中使用了useOptimistic
以后,<Thread>
组件中展示的message
列表实际上是经过处理的,在表单提交的时候,<Thread>
组件的表单提交处理函数会首先往经过useOptimistic
处理后的message
列表里添加一条临时的记录。这样看起来就变成了服务已经接受了刚刚输入的内容,但是正在进行处理。此时等到<App>
组件中的表单处理完成时,<App>
组件传递给<Thread>
组件的messages
就发生了变化,于是<Thread>
组件中展示的列表就被更新以后的messages
所替代。
所以从这个示例可以看出,useOptimistic
Hook 最大的功用就是优化在应用进行后台操作时,UI 进行提醒和临时信息展示的。善加利用可以让应用的 UI 变得更加友好。