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

React+JavaScript实现列表项AddButton单选激活的问题修复

修复单选激活按钮的双击问题

我来帮你搞定这个问题!你遇到的双击才生效的问题,根源在于两个状态源冲突了——每个AddButton自己维护了isDrawing状态,同时父组件List又有activeIndex状态,两者没有同步,导致第一次点击只更新了父组件的索引,但按钮自己的状态还没切换,第二次点击才完成同步。

要解决这个问题,我们需要把激活状态的控制权完全统一到父组件,让子组件的绘图状态依赖父组件的激活状态,而不是各自维护独立状态。以下是完整的修复方案:


1. 统一父组件的激活状态管理

修改List组件,用item的唯一标识(优先用id,没有的话用index)来跟踪当前激活项,避免多个状态源冲突:

function List({ items }: Props) {
  // 用item的唯一id跟踪激活项(如果item没有id,也可以用index)
  const [activeItemId, setActiveItemId] = React.useState<string | null>(null);

  const handleButtonClick = (itemId: string) => {
    // 点击当前激活项时,取消激活;否则设置为新的激活项
    setActiveItemId(prev => prev === itemId ? null : itemId);
  };

  return (
    <>
      {items.map((item: any) => (
        <Card key={item.id}>
          <Header>{item.title}</Header>
          <AddButton 
            item={item}
            isActive={activeItemId === item.id}
            onClick={() => handleButtonClick(item.id)}
          />
        </Card>
      ))}
    </>
  );
}

2. 修改useDrawing Hook,依赖外部激活状态

让useDrawing不再自己维护isToolActive,而是接收父组件传入的isActive状态,自动同步绘图逻辑:

const useDrawing = (isActive: boolean) => {
  const [saveableDrawing, setSaveableDrawing] = React.useState<google.maps.Drawing | null>(null);
  const isDrawing = isActive || !!saveableDrawing;

  // 当外部激活状态变化时,自动处理绘图的开启/关闭
  React.useEffect(() => {
    if (isActive) {
      // 这里写激活绘图工具的逻辑,比如初始化google.maps.Drawing
      // 示例:setSaveableDrawing(new google.maps.Drawing(...))
    } else {
      if (saveableDrawing) {
        cancelDrawing();
      }
    }
  }, [isActive]);

  const cancelDrawing = React.useCallback(() => {
    // 这里写取消绘图的逻辑,比如销毁绘图工具
    saveableDrawing?.setMap(null);
    setSaveableDrawing(null);
  }, [saveableDrawing]);

  return { isDrawing, cancelDrawing };
};

3. 简化AddButton组件,同步激活状态

去掉AddButton内部的toggle逻辑,直接使用父组件传入的激活状态和点击回调:

function AddButton({ item, isActive, onClick }: Props) {
  const { isDrawing } = useDrawing(isActive);

  return (
    <IconButton onClick={onClick} active={isDrawing} />
  );
}

改动核心说明

  • 单一状态源:激活状态完全由父组件的activeItemId控制,避免子组件独立状态导致的不同步问题。
  • 自动同步:useDrawing通过useEffect监听外部激活状态,自动处理绘图的开启/关闭,不需要手动调用toggle。
  • 简化逻辑:点击按钮只需要通知父组件切换激活项,绘图逻辑由Hook自动完成,避免双击触发两次状态更新。

如果你的item没有唯一id,也可以用index代替item.id,但推荐尽量使用唯一标识,避免列表重排导致的索引混乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 21:27:58