如何在新增数组元素时保留已有元素的随机位置?
解决方案
核心问题是你在渲染阶段实时生成随机位置,每次组件重渲染(比如新增元素触发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
相关产品推荐
相关产品推荐

