React根据路由参数裁剪数组后切换更大长度不生效该如何修复?
问题根因
- 直接修改state引用:代码中
let tempDeck = deck属于引用赋值,没有创建新的数组副本,而splice是原地修改方法,首次选择24张卡片后,原始32条完整的deck state就被截断为24条,后续选择更大的卡片数量时,已经没有完整的原始数据可以截取。 - 计算目标数组的基准错误:每次生成卡片数组时,基于上一次被截断的deck数组计算,而非原始完整的
data数组,导致数组长度只会持续缩小,无法恢复到更大的数值。 - 写法错误:
useEffect中fetch的回调写法错误,当前代码会同步执行setCards(number),而非等待fetch请求完成后执行,同时useParams返回的number是字符串类型,没有做类型转换,可能出现隐式类型转换问题。
修复方案
修改Images.js的核心逻辑,每次生成都基于原始完整的data数组创建副本,避免修改原始数据,同时修正相关写法,修复后代码如下:
// Images.js import { useState, useEffect } from 'react'; import { useParams } from 'react-router-dom'; // 原始完整卡片数据,保持只读不要直接修改 const data = [ { id:1, src:'https://###.com/###', }, // 剩余31条完整卡片数据 ]; const Images = () => { const { number } = useParams(); const [deck, setDeck] = useState(data); useEffect(() => { // 转数字,避免字符串类型导致的计算错误 const cardCount = Number(number); // 不需要fetch的话可以直接调用setCards(cardCount) fetch(`http://localhost:3000/play/${cardCount}`) .then(res => res.json()) // 若需要使用接口返回数据可保留该行 .then(() => setCards(cardCount)); }, [number]); const setCards = (count) => { // 每次都从原始完整data生成新副本,不修改原始数据 const tempDeck = [...data]; // 用非原地修改的slice截取前count个元素,替代splice更安全 const targetDeck = tempDeck.slice(0, count); shuffle(targetDeck); setDeck(targetDeck); }; // 剩余组件渲染逻辑 };
额外说明
如果你的业务逻辑需要基于上一次的deck数组做修改而非重置为原始数据,可以使用state的函数式更新写法避免闭包陷阱:
setDeck(prevDeck => { const newDeck = [...prevDeck]; // 自定义修改逻辑 return newDeck; })
内容的提问来源于stack exchange,提问作者mateuszlaczynski
相关产品推荐
相关产品推荐

