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

React新手求助:实现点击.group-item向layers组件传值并显示dropdown

React Layer 下拉菜单实现方案

核心思路

通过父组件统一托管状态,实现Header(触发层)和Layers(展示层)的通信,符合React单向数据流原则,解决兄弟组件直接通信的问题。

1. 父组件(App.js)状态管理

在App组件中维护layers数组状态,同时提供添加、移除layer的方法,传递给子组件:

import { useState } from "react";
import Header from "./Header";
import Layers from "./Layers";

function App() {
  const [layers, setLayers] = useState([]);

  // 添加layer:接收playerID、点击坐标
  const addLayer = (playerId, x, y) => {
    setLayers(prev => [...prev, {
      id: Date.now(),
      type: 1,
      playerId,
      position: { x, y }
    }]);
  };

  // 移除layer:用于关闭下拉菜单
  const removeLayer = (layerId) => {
    setLayers(prev => prev.filter(layer => layer.id !== layerId));
  };

  return (
    <div className="App">
      <Header onAddLayer={addLayer} />
      <Layers layers={layers} onRemoveLayer={removeLayer} />
    </div>
  );
}

export default App;

2. Header组件(触发点击事件)

给.group-item绑定点击事件,获取playerID和点击坐标,调用父组件传递的addLayer方法:

import "./Header.css";

export default function Header({ onAddLayer }) {
  const players = [
    { id: 1, name: "Player 1" },
    { id: 2, name: "Player 2" },
    { id: 3, name: "Player 3" }
  ];

  const handleItemClick = (e, playerId) => {
    const { clientX, clientY } = e;
    onAddLayer(playerId, clientX, clientY);
  };

  return (
    <div className="header">
      <div className="group">
        {players.map(player => (
          <div
            key={player.id}
            className="group-item"
            onClick={(e) => handleItemClick(e, player.id)}
          >
            {player.name}
          </div>
        ))}
      </div>
    </div>
  );
}

3. Layers组件(渲染下拉菜单)

接收layers数组,根据type和位置渲染下拉菜单,展示playerID和坐标,同时支持关闭:

import "./Layers.css";

export default function Layers({ layers, onRemoveLayer }) {
  return (
    <div className="layers-container">
      {layers.map(layer => (
        layer.type === 1 && (
          <div
            key={layer.id}
            className="dropdown-layer"
            style={{
              position: "fixed",
              left: `${layer.position.x}px`,
              top: `${layer.position.y}px`,
              transform: "translate(-50%, 10px)"
            }}
          >
            <div className="dropdown-content">
              <p>Player ID: {layer.playerId}</p>
              <p>点击坐标: ({layer.position.x}, {layer.position.y})</p>
              <button onClick={() => onRemoveLayer(layer.id)}>关闭</button>
            </div>
          </div>
        )
      ))}
    </div>
  );
}

4. 补充样式(可选)

给下拉菜单添加基础样式,避免遮挡下层元素:

.layers-container {
  pointer-events: none;
}

.dropdown-layer {
  pointer-events: auto;
}

.dropdown-content {
  background: #fff;
  border: 1px solid #e0e0e0;
  border-radius: 4px;
  padding: 12px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}

原代码报错原因

大概率是状态未在合适层级托管,兄弟组件直接通信违反React数据流规则;或是点击事件中获取playerID、坐标的方式错误,导致数据传递异常。上述方案通过父组件统一管理状态,彻底解决这类问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 09:20:42