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

React表单中通讯渠道按钮独立切换状态的问题求助

问题:通讯渠道图标无法独立切换状态

实现包含邮箱和WhatsApp的表单时,点击其中一个渠道的开关图标,两个图标会同步变化,无法独立控制各自的通知状态,同时需要同步更新内存中的用户数据。

问题根源

当前用单个checked状态变量同时控制两个渠道的显示,点击时会同时反转这个变量的值,导致两个图标同步切换。

解决方案

直接利用react-hook-form的表单状态管理各渠道的开关,不用单独维护状态,同时实现精准更新:

1. 移除独立的checked状态,复用表单状态

删掉原来的useState声明,改用react-hook-form的watch和setValue来管理和更新各渠道的notification值。

2. 编写通用的切换函数

写一个接收渠道名称的函数,只更新对应渠道的通知状态:

const toggleNotification = (channel) => {
  const currentValue = communicationWatch[channel].notification;
  setValue(`communication[0].${channel}.notification`, !currentValue);
};

3. 按渠道状态渲染图标

通过watch获取对应渠道的notification值,判断显示勾选还是取消图标:

修改后的完整代码

import { useForm } from "react-hook-form";
import { CheckCircleIcon, XCircleIcon } from "@heroicons/react/24/solid";

export default function CommunicationForm() {
  const { register, watch, setValue } = useForm({
    initialValues: {
      email: "",
      communication: [
        {
          email: {
            email: "",
            notification: true,
          },
          whatsapp: {
            notification: false,
          },
        },
      ],
    },
  });

  // 实时监听通讯渠道的状态
  const communicationWatch = watch("communication[0]");

  // 切换指定渠道的通知状态
  const toggleNotification = (channel) => {
    const currentStatus = communicationWatch[channel].notification;
    setValue(`communication[0].${channel}.notification`, !currentStatus);
  };

  return (
    <form>
      <table>
        <thead>
          <tr>
            <th>通讯渠道</th>
            <th>通知状态</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>Email</td>
            <td>
              {communicationWatch.email.notification ? (
                <CheckCircleIcon
                  className="h-6 w-6 text-green-500 cursor-pointer"
                  onClick={() => toggleNotification("email")}
                />
              ) : (
                <XCircleIcon
                  className="h-6 w-6 text-red-500 cursor-pointer"
                  onClick={() => toggleNotification("email")}
                />
              )}
            </td>
          </tr>
          <tr>
            <td>WhatsApp</td>
            <td>
              {communicationWatch.whatsapp.notification ? (
                <CheckCircleIcon
                  className="h-6 w-6 text-green-500 cursor-pointer"
                  onClick={() => toggleNotification("whatsapp")}
                />
              ) : (
                <XCircleIcon
                  className="h-6 w-6 text-red-500 cursor-pointer"
                  onClick={() => toggleNotification("whatsapp")}
                />
              )}
            </td>
          </tr>
        </tbody>
      </table>
    </form>
  );
}

关键说明

  • 所有状态都保存在react-hook-form的表单值中,保证UI和内存数据同步,后续提交表单时直接获取最新状态即可。
  • 切换函数通过渠道参数精准定位要更新的字段,不会影响其他渠道。
  • 给图标添加cursor-pointer样式,提升交互体验。

内容的提问来源于stack exchange,提问作者Somdotta Sarkar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 07:35:22