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

React+TS开发Cookie类点击器:随机弹窗元素不显示问题求助

问题:随机弹窗元素无法显示

开发Cookie类点击器时,遇到随机弹窗元素完全不显示的问题,目标是实现类似Cookie Clicker中金饼干的功能:元素按随机间隔在屏幕随机位置出现,点击后触发相应操作。

相关代码

Caravan.tsx

interface CaravanProps{
    x: number;
    y:number;
  }

function randomNumberBetween(min: number, max: number): number {
  return Math.random() * (max - min) + min;
}

export let CaravanGen = () => {
  let caravanList: Array<JSX.Element> = new Array<JSX.Element>();
  const[carList, setCarList] = useState(caravanList);

  useEffect(() => {
    let timer = randomNumberBetween(3000, 6000);
    let newCarList = carList;

    const interval = setInterval(() => {
      const x = randomNumberBetween(0, 1900);
      const y = randomNumberBetween(0, 1000);
      newCarList.push(<Caravan x={x} y={y}/>);
      setCarList(newCarList);
      console.log(x, y);
    }, timer);

    return () => {
      clearInterval(interval);
    };
  }, []);

  return(<div className='caravan-gen'>{caravanList}</div>);
}  

export function Caravan(props: CaravanProps) {
  
    return(
      <div style={{
        position: 'absolute',
        left: props.x,
        top: props.y,
        width: "100px",
        height: "100px",
        borderRadius: "100%",
        backgroundColor: "black"
      }}>
      </div>
    );
  }

index.css

.caravan-pop{
  width: 100px;
  height: 100px;
  border-radius: 100%;
  background-color: black;
  z-index: 10;
}

修复方案

核心问题与修复点

  1. 渲染对象错误:CaravanGen返回的是初始空数组caravanList,而非状态变量carList,状态更新后视图不会同步刷新,需改为渲染{carList}。
  2. 数组引用未更新:直接赋值let newCarList = carList是复用原数组引用,push修改后React无法检测到状态变化,必须创建新数组(如const newCarList = [...carList])。
  3. 定时器间隔固定:当前timer仅初始化一次,后续弹窗都会用同一个间隔,不符合随机需求,改用递归setTimeout实现每次生成新的随机间隔。
  4. 父容器定位缺失:绝对定位的子元素需要父容器设置position: relative,否则会相对于整个文档定位,容易超出可视区域。

修复后的CaravanGen组件

export let CaravanGen = () => {
  const [carList, setCarList] = useState<JSX.Element[]>([]);

  useEffect(() => {
    const generateCaravan = () => {
      const timer = randomNumberBetween(3000, 6000);
      const timeoutId = setTimeout(() => {
        // 计算位置时减去元素尺寸,确保完全显示在可视区内
        const x = randomNumberBetween(0, window.innerWidth - 100);
        const y = randomNumberBetween(0, window.innerHeight - 100);
        // 用函数式更新创建新数组,避免依赖外部状态
        setCarList(prev => [...prev, <Caravan key={Date.now() + Math.random()} x={x} y={y}/>]);
        generateCaravan(); // 递归调用,实现下一次随机间隔
      }, timer);
      return timeoutId;
    };

    const timeoutId = generateCaravan();
    return () => clearTimeout(timeoutId);
  }, []);

  // 父容器设置相对定位和最小高度,确保弹窗定位正常
  return(<div className='caravan-gen' style={{position: 'relative', minHeight: '100vh'}}>{carList}</div>);
}

补充说明

  • 给每个Caravan元素添加唯一key,避免React列表渲染警告。
  • 计算x/y坐标时减去元素宽高,防止弹窗超出屏幕可视范围。
  • 父容器设置minHeight: '100vh',确保占满整个视口高度,避免弹窗位置异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 02:40:03