You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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。

修正后的核心逻辑建议

  1. 调整updateUserAdminAccess的参数,根据checked值设置目标角色
  2. 移除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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 06:55:09