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

如何在新增数组元素时保留已有元素的随机位置?

解决方案

核心问题是你在渲染阶段实时生成随机位置,每次组件重渲染(比如新增元素触发setData后),所有元素都会重新执行randomNum生成新位置。要解决这个问题,需要把随机位置和元素数据绑定在一起,仅在元素创建时生成一次位置,后续渲染直接复用已有位置。

步骤1:修改数据结构,新增元素时生成随机位置

在新增元素的函数里,直接为新对象生成并存储随机位置,而不是等到渲染时再生成:

const randomNum = (min: number, max: number): number => {
  return Math.floor(Math.random() * (max - min + 1) + min);
};

function handleAddInput(id: number) {
  setData(
    update(data, {
      data: {
        $push: [
          {
            name: '',
            id,
            // 新增时直接生成随机位置并存入对象
            top: `${randomNum(0, 51)}%`,
            right: `${randomNum(0, 51)}%`,
          } as any,
        ],
      },
    })
  );
}

步骤2:渲染时直接复用已有位置

修改渲染逻辑,不再调用randomNum,而是直接读取元素对象中存储的位置值:

const elements = data.data.map((item: any) => {
  return (
    <Fade left key={item.id}> {/* 必须添加唯一key,避免React渲染警告 */}
      <div
        style={{
          position: 'absolute',
          top: item.top,
          right: item.right,
        }}
      >
        <Image alt="Smiley" src={smiley} />
      </div>
    </Fade>
  );
});

步骤3:处理初始数据的位置初始化(可选)

如果组件挂载时已有初始数据,需要给这些初始元素也生成随机位置,用useEffect在组件首次挂载时执行一次:

import { useEffect } from 'react';

useEffect(() => {
  // 检查初始数据是否已包含位置字段,没有则初始化
  if (data.data.length > 0 && !data.data[0].top) {
    const initializedData = update(data, {
      data: {
        $set: data.data.map(item => ({
          ...item,
          top: `${randomNum(0, 51)}%`,
          right: `${randomNum(0, 51)}%`,
        }))
      }
    });
    setData(initializedData);
  }
}, []); // 空依赖数组确保仅在组件挂载时执行一次

原理说明

把随机位置和元素数据绑定后,每个元素的位置只在创建时生成一次:新增元素时生成新位置,已有元素的位置存储在数据中不会改变,组件重渲染时直接复用这些值,就不会出现所有元素位置重置的问题了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 14:10:25