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
相关产品推荐
相关产品推荐

