useOptimistic Hook能否用于布尔值?开关组件乐观更新异常
关于React useOptimistic Hook与布尔值乐观更新的问题
我有一个Switch组件,其checked值会根据用户是否为管理员进行更新,更新完成后会重新获取数据。点击开关时,组件仍需等待加载完成后才会更新,未实现预期的「先更新再重新验证」效果。
相关代码如下:
import React, { useOptimistic } from 'react'; import { Switch } from '@/components/ui/switch'; import { FirebaseUser } from '@/typings/user'; import { QueryObserverResult, RefetchOptions } from '@tanstack/react-query'; import { updateUserAdminAccess } from '@/services/admin'; import { toast } from 'sonner'; import { AxiosError } from 'axios'; const ControlUserAdminSwitch: React.FC<ControlUserAdminSwitchProps> = ({ role, uid, refetch, }) => { const [isAdmin, setIsAdmin] = useOptimistic(role === 'ADMIN'); const handleUpdateUserAccess = async (checked: boolean) => { try { await updateUserAdminAccess(uid, role); toast.success( `User admin access ${checked ? 'granted' : 'revoked'} successfully.` ); } catch (error) { if (error instanceof AxiosError) { switch (error.response?.data.message) { case 'app/user-not-found': { toast.error('User not found'); break; } case 'app/user-admin-access-failed': { toast.error('User admin access update failed'); break; } default: { toast.error('Unable to update user admin access. Please try again later.'); } } } } finally { refetch(); } }; return ( <Switch checked={isAdmin} onCheckedChange={(checked) => { setIsAdmin(checked); handleUpdateUserAccess(checked); }} /> ); };
疑问
请问useOptimistic Hook能否用于布尔值?乐观更新是否仅支持数组类型,还是也支持布尔值类型?
解答
useOptimistic Hook完全支持布尔值类型,并非仅局限于数组。它可以处理任何可序列化的JavaScript值,包括布尔值、字符串、数字、对象等。
你当前代码未实现预期效果的问题,并非类型不支持导致,而是出在refetch的时机和useOptimistic的使用逻辑上:
- 在
finally中调用refetch()会覆盖乐观更新的状态,因为refetch完成后组件会重新接收props中的role值,导致useOptimistic的状态被重置为初始值。 - 另外,
updateUserAdminAccess的调用参数存在错误:应该根据checked值传递对应的目标角色(比如checked为true时传'ADMIN',否则传普通角色),而非直接传入当前的role。
修正后的核心逻辑建议
- 调整
updateUserAdminAccess的参数,根据checked值设置目标角色 - 移除
finally里的refetch,请求失败时手动回退乐观更新的状态
示例修正后的handleUpdateUserAccess函数:
const handleUpdateUserAccess = async (checked: boolean) => { // 根据checked值设置目标角色,需根据实际业务调整普通角色值 const targetRole = checked ? 'ADMIN' : 'USER'; try { await updateUserAdminAccess(uid, targetRole); toast.success( `User admin access ${checked ? 'granted' : 'revoked'} successfully.` ); } catch (error) { // 请求失败,回退到原始状态 setIsAdmin(role === 'ADMIN'); if (error instanceof AxiosError) { switch (error.response?.data.message) { case 'app/user-not-found': toast.error('User not found'); break; case 'app/user-admin-access-failed': toast.error('User admin access update failed'); break; default: toast.error('Unable to update user admin access. Please try again later.'); } } } };
总结
- useOptimistic支持布尔值,你的问题与类型支持无关
- 核心问题是请求参数错误和状态重置逻辑不当,导致乐观更新的效果被覆盖
内容的提问来源于stack exchange,提问作者kunalkeshan
相关产品推荐
相关产品推荐

