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

如何修改React Box Shadow Generator实现删除层后保留原层名

解决Box Shadow Generator删除层后保留原层名的问题

当前实现的核心问题是层名完全依赖数组索引生成,删除中间层后数组索引重排,导致后续层的名称被自动修改。要保留原层名,需给每个阴影层添加独立标识和固定名称,不再依赖数组索引。

修改思路

  • 给每个阴影对象添加id(唯一标识)和name(固定层名)属性
  • 将选中状态从存储数组索引改为存储选中层的id
  • 所有依赖索引的操作(获取选中层、删除层等)改为通过id查找对应元素
  • 渲染层列表和控制区域标题时,使用层的name属性而非索引

修改后的完整代码

import "./boxShadowGenerator.css";
import React, { useState, useRef, useEffect } from "react";

export const BoxShadowGenerator = () => {
  const [boxShadows, setBoxShadows] = useState([]);
  const [selectedLayerId, setSelectedLayerId] = useState(null);
  const buttonRefs = useRef({});

  // 添加新层时生成唯一ID和固定层名
  const addBoxShadow = () => {
    // 计算新层编号:取现有层最大编号+1,无现有层则从1开始
    const maxLayerNumber = boxShadows.length 
      ? Math.max(...boxShadows.map(layer => parseInt(layer.name.split(' ')[1]))) 
      : 0;
    const newLayerNumber = maxLayerNumber + 1;
    
    const newBoxShadow = {
      id: Date.now(), // 用时间戳作为唯一标识
      name: `Layer ${newLayerNumber}`,
      hOffset: 0,
      vOffset: 0,
      blurRadius: 0,
      spreadRadius: 0,
      color: "#000",
    };
    const newBoxShadows = [...boxShadows, newBoxShadow];
    setBoxShadows(newBoxShadows);
    setSelectedLayerId(newBoxShadow.id); // 默认选中新添加的层
  };

  // 通过ID删除指定层
  const removeBoxShadow = (layerId) => {
    const newBoxShadows = boxShadows.filter(layer => layer.id !== layerId);
    setBoxShadows(newBoxShadows);
    // 如果删除的是当前选中层,自动选中第一个剩余层
    if (selectedLayerId === layerId && newBoxShadows.length > 0) {
      setSelectedLayerId(newBoxShadows[0].id);
    }
  };

  const copyToClipboard = () => {
    const boxShadow = boxShadows
      .map(
        ({ hOffset, vOffset, blurRadius, spreadRadius, color }) =>
          `${hOffset}px ${vOffset}px ${blurRadius}px ${spreadRadius}px ${color}`
      )
      .join(", ");
    navigator.clipboard.writeText(`box-shadow:${boxShadow};`);
  };

  // 获取当前选中的层对象
  const selectedLayer = boxShadows.find(layer => layer.id === selectedLayerId);

  useEffect(() => {
    if (selectedLayerId && buttonRefs.current[selectedLayerId]) {
      buttonRefs.current[selectedLayerId].focus();
    }
  }, [selectedLayerId]);

  return (
    <>
      <div className="BSG-main-container">
        <div className="BSG-control-container">
          <h2>Box Shadow Generator</h2>
          <div
            className="box-preview"
            style={{
              boxShadow: boxShadows
                .map(
                  ({ hOffset, vOffset, blurRadius, spreadRadius, color }) =>
                    `${hOffset}px ${vOffset}px ${blurRadius}px ${spreadRadius}px ${color}`
                )
                .join(", "),
            }}
          ></div>

          {selectedLayer && (
            <div>
              <h3>{selectedLayer.name}</h3>
              <div>
                <label htmlFor={`hOffset${selectedLayer.id}`}>
                  Horizontal offset:
                </label>
                <input
                  type="range"
                  id={`hOffset${selectedLayer.id}`}
                  min="-50"
                  max="50"
                  value={selectedLayer.hOffset}
                  onChange={(e) => {
                    setBoxShadows(boxShadows.map(layer => 
                      layer.id === selectedLayerId 
                        ? {...layer, hOffset: parseInt(e.target.value)} 
                        : layer
                    ));
                  }}
                />
              </div>
              <div>
                <label htmlFor={`vOffset${selectedLayer.id}`}>
                  Vertical offset:
                </label>
                <input
                  type="range"
                  id={`vOffset${selectedLayer.id}`}
                  min="-50"
                  max="50"
                  value={selectedLayer.vOffset}
                  onChange={(e) => {
                    setBoxShadows(boxShadows.map(layer => 
                      layer.id === selectedLayerId 
                        ? {...layer, vOffset: parseInt(e.target.value)} 
                        : layer
                    ));
                  }}
                />
              </div>
              <div>
                <label htmlFor={`blurRadius${selectedLayer.id}`}>
                  Blur radius:
                </label>
                <input
                  type="range"
                  id={`blurRadius${selectedLayer.id}`}
                  min="0"
                  max="50"
                  value={selectedLayer.blurRadius}
                  onChange={(e) => {
                    setBoxShadows(boxShadows.map(layer => 
                      layer.id === selectedLayerId 
                        ? {...layer, blurRadius: parseInt(e.target.value)} 
                        : layer
                    ));
                  }}
                />
              </div>
              <div>
                <label htmlFor={`spreadRadius${selectedLayer.id}`}>
                  Spread radius:
                </label>
                <input
                  type="range"
                  id={`spreadRadius${selectedLayer.id}`}
                  min="-50"
                  max="50"
                  value={selectedLayer.spreadRadius}
                  onChange={(e) => {
                    setBoxShadows(boxShadows.map(layer => 
                      layer.id === selectedLayerId 
                        ? {...layer, spreadRadius: parseInt(e.target.value)} 
                        : layer
                    ));
                  }}
                />
              </div>
              <div>
                <label htmlFor={`color${selectedLayer.id}`}>Color:</label>
                <input
                  type="color"
                  id={`color${selectedLayer.id}`}
                  value={selectedLayer.color}
                  onChange={(e) => {
                    setBoxShadows(boxShadows.map(layer => 
                      layer.id === selectedLayerId 
                        ? {...layer, color: e.target.value} 
                        : layer
                    ));
                  }}
                />
              </div>
            </div>
          )}
          <div className="buttons">
            <button onClick={addBoxShadow}>Add Layer</button>
            {boxShadows.length > 0 && (
              <>
                <button onClick={() => removeBoxShadow(selectedLayerId)}>
                  Remove Layer
                </button>
                <button onClick={copyToClipboard}>Copy CSS to Clipboard</button>
              </>
            )}
          </div>
        </div>
        {boxShadows.length > 0 && (
          <div className="box-shadow-list-container">
            {boxShadows.map((boxShadow) => (
              <button
                ref={(button) => (buttonRefs.current[boxShadow.id] = button)}
                key={boxShadow.id}
                className={`box-shadow-list-item ${selectedLayerId === boxShadow.id ? "selected" : ""}`}
                onClick={() => setSelectedLayerId(boxShadow.id)}
              >
                {boxShadow.name}
              </button>
            ))}
          </div>
        )}
      </div>
    </>
  );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 01:55:35