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

React组件状态更新异常:单选类切换失效问题求助

问题描述

我尝试通过切换checked-radio-btn类来显示/隐藏内容,首次点击时类能正常应用,但切换到其他元素时,前一个元素的类无法移除,希望同一时间只有一个元素处于选中状态。目前组件状态更新异常,而我正是基于这个状态来切换类的。相关组件代码如下:

function ProjectItem({ productName, totalPledge, productDescription, totalLeft, index }) {

    const [isActive, setIsActive] = useState('')

    useEffect(() => {
        console.log(isActive)
    }, [isActive]);

    const handleCheckedProduct = (value) => {
        setIsActive(value);
    }

    return (
        <div className={`product ${index === isActive ? 'checked-radio-btn' : ''} ${index}`} >
            <input type="radio" name='product' id={productName} value={totalPledge} onClick={() => { handleCheckedProduct(index) }} />
            <label className='radio-btn' htmlFor={productName} onClick={() => { handleCheckedProduct(index) }}></label>
            <div className='product-name'>
                <label htmlFor={productName} onClick={() => { handleCheckedProduct(index) }}>{productName}</label><span>Pledge ${totalPledge} or more</span>
            </div>
            <div className='product-left'>
                <span>{totalLeft}</span><span>left</span>
            </div>
            <div className='product-description'>{productDescription}</div>
            <div className={`back-product ${index === isActive ? 'checked-radio-btn' : ''}`}>
                <div>Enter your pledge</div>
                <div className='project-pledge-btn' >
                    <div className='project-input-btn'>
                        <input type='text' defaultValue={totalPledge} />
                    </div>
                    <button>continue</button>
                </div>
            </div>
        </div>
    )
} 
解决方案

问题核心在于每个ProjectItem组件都维护了自己独立的isActive状态,多个组件之间状态无法同步——选中新组件时,旧组件的状态不会被更新,所以它的checked-radio-btn类不会被移除。

要实现全局唯一选中的效果,需要把状态提升到父组件统一管理:

  • 父组件维护选中状态
    在渲染ProjectItem列表的父组件中添加状态,控制当前选中的索引:

    // 父组件示例代码
    import { useState } from 'react';
    import ProjectItem from './ProjectItem';
    
    function ProjectList() {
      const [activeIndex, setActiveIndex] = useState(null);
    
      return (
        <div className="project-list">
          {products.map((product, index) => (
            <ProjectItem
              key={index}
              {...product}
              index={index}
              isActive={index === activeIndex}
              onSelect={() => setActiveIndex(index)}
            />
          ))}
        </div>
      );
    }
    
  • 修改子组件,使用父组件传递的状态
    删掉子组件自身的isActive状态,改用父组件传入的props:

    function ProjectItem({ productName, totalPledge, productDescription, totalLeft, index, isActive, onSelect }) {
    
      return (
        <div className={`product ${isActive ? 'checked-radio-btn' : ''} ${index}`} >
          <input 
            type="radio" 
            name='product' 
            id={productName} 
            value={totalPledge} 
            onClick={onSelect}
            checked={isActive}
          />
          <label className='radio-btn' htmlFor={productName} onClick={onSelect}></label>
          <div className='product-name'>
            <label htmlFor={productName} onClick={onSelect}>{productName}</label><span>Pledge ${totalPledge} or more</span>
          </div>
          <div className='product-left'>
            <span>{totalLeft}</span><span>left</span>
          </div>
          <div className='product-description'>{productDescription}</div>
          <div className={`back-product ${isActive ? 'checked-radio-btn' : ''}`}>
            <div>Enter your pledge</div>
            <div className='project-pledge-btn' >
              <div className='project-input-btn'>
                <input type='text' defaultValue={totalPledge} />
              </div>
              <button>continue</button>
            </div>
          </div>
        </div>
      )
    } 
    
  • 额外优化
    给radio按钮加上checked={isActive}属性,让原生radio的选中状态和组件视觉状态保持一致,符合表单原生行为;同时移除子组件中多余的useState和useEffect,减少无意义的状态管理。

修改后所有ProjectItem的选中状态由父组件统一控制,就能保证同一时间只有一个元素带有checked-radio-btn类,实现单选效果。

内容的提问来源于stack exchange,提问作者Md Mazhar Ali

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 18:02:37