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

React中多个同类名place-box点击切换全部触发如何解决?

问题修复方案

问题原因

你的猜测不对,该问题和类名没有关联。核心原因是你把isOpen定义为CityResult组件的全局状态,所有循环渲染出来的place-box元素共用这一个布尔值做展示判断,只要状态更新,所有元素都会同步切换展示效果。

修复方案

方案1:仅允许单个地点同时展开(匹配你现有交互预期)

你已经在存储点击的地点id,可以直接复用该状态,无需额外的isOpen变量,修改后代码如下:

import React, { useState } from "react";
import { useQuery } from "@apollo/client";
import { FETCH_CITIES_QUERY } from "../../server/Data/RentQueries";
import PlaceResult from "../Rent/PlaceResult";

const CityResult = (props) => {
  // 仅存储当前激活展开的地点id,为null则全部关闭
  const [activePlaceId, setActivePlaceId] = useState(null);
  // 补全你代码中缺失的cityName变量提取
  const cityName = props.cityName;
    
  const { loading, error, data } = useQuery(FETCH_CITIES_QUERY, {
    variables: { cityName: cityName },
  });

  const showPlaceInfo = (clickedPlaceId, e) => {
    e.preventDefault();
    // 点击同一个则关闭,点击不同则切换为对应id
    setActivePlaceId(prevId => prevId === clickedPlaceId ? null : clickedPlaceId);
  };

  return (
    <div>
      {data &&
        data.cities.map((city) => {
          return (
            <div className="city-box" key={city.id}>
              {city.places.map((place) => {
                return (
                  <div
                    className="place-box"
                    key={place.id}
                    onClick={(e) => {
                      e.stopPropagation();
                      showPlaceInfo(place.id, e);
                    }}
                  >
                    <li className="place-name">{place.name}</li>
                    {/* 判断当前place的id是否等于激活id,决定展示内容 */}
                    {place.id === activePlaceId ? (
                      <PlaceResult className="place-indiv" placeId={place.id} />
                    ) : (
                      <div className="place-info-box">
                        <li>{place.address}</li>
                        {conditionCheck(city.condition)}
                        <li>{place.phone}</li>
                      </div>
                    )}
                  </div>
                );
              })}
            </div>
          );
        })}
    </div>
  );
};

export default CityResult;

方案2:允许多个地点同时展开

如果需要支持同时打开多个地点卡片,可以用Set存储所有已展开的地点id:

// 状态定义
const [openPlaceIds, setOpenPlaceIds] = useState(new Set());

// 点击逻辑
const togglePlaceInfo = (clickedPlaceId, e) => {
  e.preventDefault();
  setOpenPlaceIds(prev => {
    const newSet = new Set(prev);
    if (newSet.has(clickedPlaceId)) {
      newSet.delete(clickedPlaceId);
    } else {
      newSet.add(clickedPlaceId);
    }
    return newSet;
  })
}

// 渲染判断
{openPlaceIds.has(place.id) ? (
  <PlaceResult className="place-indiv" placeId={place.id} />
) : (
  // 省略默认展示内容
)}

额外提示

你原有代码中useQuery的variables里引用的cityName没有定义,记得从props中提取该变量,否则会触发变量未定义报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 05:24:06