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

React中useState影响同一组件多实例的问题及修复方法

问题:React组件批量渲染后点击展开按钮所有实例同步展开

我基于useState实现了一个点击按钮展开指定区域的组件,但通过map渲染多个组件实例后,点击其中一个的展开按钮,所有实例都会跟着展开。

我的组件代码:

const ContainerMenu: React.FC<ContainerMenuProps> = (props: ContainerMenuProps) => {
    const [expanded, setExpanded] = useState(false);

    return (
        <>
            <div className={`docker-container-menu ${expanded}`}>
                <button onClick={() => setExpanded(!expanded)} className='chevron-button'>
                    <Icon path={mdiChevronDown} size={1} />
                </button>
                {expanded && <div className='docker-container-menu-expanded'>
                    <button style={{ cursor: "pointer" }} onClick={() => props.startContainer(props.Id)}>
                        <Icon style={{color: "green"}} path={mdiPlay} size={1} />
                    </button>
                    <button style={{ cursor: "pointer" }} onClick={() => props.stopContainer(props.Id)}>
                        <Icon style={{color: "red"}} path={mdiStop} size={1} />
                    </button> 
                </div>}
            </div>
        </>
    )
}

列表渲染代码(已传递唯一Id作为props):

return (
    <>
        <div className="app-main-container">
            <div className="docker-containers">
                {containers.map((container: ContainerProps) => {
                    return (
                        <Container Id={container.Id} State={container.State} Status={container.Status}
                            Names={container.Names} Labels={container.Labels}/>
                    )
                })}
            </div>
        </div>
    </>
)

解决方法

1. 给列表项添加唯一key属性

React在渲染列表时需要通过唯一key区分不同组件实例,缺少key会导致React复用组件,引发状态混乱。修改列表渲染代码:

{containers.map((container: ContainerProps) => {
    return (
        <Container 
            key={container.Id}
            Id={container.Id} 
            State={container.State} 
            Status={container.Status}
            Names={container.Names} 
            Labels={container.Labels}
        />
    )
})}

2. 优化类名拼接逻辑

原代码中直接将布尔值expanded作为类名,会生成docker-container-menu true这类不规范的类名,建议转为字符串类名:

const ContainerMenu: React.FC<ContainerMenuProps> = (props: ContainerMenuProps) => {
    const [expanded, setExpanded] = useState(false);

    return (
        <>
            <div className={`docker-container-menu ${expanded ? 'expanded' : ''}`}>
                <button onClick={() => setExpanded(!expanded)} className='chevron-button'>
                    <Icon path={mdiChevronDown} size={1} />
                </button>
                {expanded && <div className='docker-container-menu-expanded'>
                    <button style={{ cursor: "pointer" }} onClick={() => props.startContainer(props.Id)}>
                        <Icon style={{color: "green"}} path={mdiPlay} size={1} />
                    </button>
                    <button style={{ cursor: "pointer" }} onClick={() => props.stopContainer(props.Id)}>
                        <Icon style={{color: "red"}} path={mdiStop} size={1} />
                    </button> 
                </div>}
            </div>
        </>
    )
}

原因说明

  • 缺少key时,React无法识别列表中每个组件的唯一性,会复用已有组件实例,导致单个组件的状态变化被同步到所有实例。
  • 规范类名拼接可以避免样式逻辑出现意外问题,确保展开样式正确生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 20:57:04