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

React多实例Item组件单选状态控制:仅修改组件可行吗?

实现单选效果的方案

仅修改Item组件无法实现单选效果,必须修改引入它的父组件。原因是每个Item实例的isSelected都是自身独立的本地状态,各实例之间无法共享或同步状态,自然做不到选中一个时自动取消其他的选中状态。

修改方案

  • 父组件统一管理选中状态
    • 父组件维护一个状态变量,记录当前选中的Item标识(比如name)
    • 父组件提供一个回调函数,用于接收子组件的选中事件并更新状态
  • 调整Item组件为受控组件
    • 移除Item内部的isSelected本地状态,改为通过props接收父组件传递的选中状态和回调函数
    • 点击时触发父组件的回调,告知父组件自己被选中
    • 根据父组件传递的选中状态渲染按钮样式和文本

修改后的代码示例

父组件(示例命名为ItemList)

import React, { useState } from "react";
import Item from "./Item";

const ItemList = () => {
  // 记录当前选中的Item的name,初始为null表示无选中项
  const [selectedItemName, setSelectedItemName] = useState(null);

  const handleSelectItem = (name) => {
    // 如果点击的是已选中的项,取消选中;否则设置为当前项
    setSelectedItemName(selectedItemName === name ? null : name);
  };

  // 示例列表数据
  const items = ["项目A", "项目B", "项目C"];

  return (
    <div>
      {items.map(name => (
        <Item
          key={name}
          name={name}
          // 传递当前Item是否被选中
          isSelected={selectedItemName === name}
          // 传递选中回调
          onSelect={() => handleSelectItem(name)}
        />
      ))}
    </div>
  );
};

export default ItemList;

修改后的Item组件

import React from "react";
import Button from "./Button";

const Item = ({ name, isSelected, onSelect }) => {
  // 根据父组件传递的isSelected直接判断样式和文本
  const buttonColor = isSelected ? "bg-button-blue" : "bg-button-gray";
  const buttonText = isSelected ? "Selected" : "Select";

  return (
    <div onClick={onSelect} className="flex ml-2 items-center">
      <div className="text-misc-gray text-xs w-40">{name}</div>
      <div>
        <Button
          text={buttonText}
          color={buttonColor}
          height="h-8"
          width="w-18"
        />
      </div>
    </div>
  );
};

export default Item;

这样修改后,所有Item的选中状态由父组件统一控制,就能实现点击任意一个Item时,自动取消之前选中的项,达到单选效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 11:55:28