JS使用useState合并新旧数组为一维数组及类型报错问题咨询
问题排查与解决方案
错误原因
- 类型不匹配:你声明的
start是Date[]类型的一维数组,而holidayDates本身就是Date[]类型,直接写[...start, holidayDates]会把整个holidayDates数组作为单个元素插入,最终得到的是混合了Date和Date数组的二维结构,和声明的Date[]类型冲突,所以触发TS报错。 - 状态更新逻辑错误:循环内直接使用当前
start值更新状态时,React的状态更新是批量异步的,多次调用setStart时拿到的start都是初始值,最终只会保留最后一次循环的更新结果,之前的合并结果会被覆盖。
实现方案
方案一:先计算完整数组再一次性更新(推荐)
先遍历所有节假日计算出所有日期,合并成一维数组后只执行一次状态更新,性能更高:
const [start, setStart] = useState<Date[]>([]); useEffect(() => { if (!publicHoliday) return; // flatMap会自动把每个返回的数组合并为一维数组 const allHolidayDates = publicHoliday.flatMap(holiday => { const eventStartDate = holiday.startDate; const eventEndDate = holiday.endDate; return enumerateDaysBetweenDates(eventStartDate, eventEndDate); }); setStart(allHolidayDates); }, [publicHoliday]);
方案二:循环内使用函数式更新
如果需要在循环中逐步更新状态,可以使用setState的函数式更新写法,每次更新都能拿到上一次的最新状态,同时要展开holidayDates保证数组是一维结构:
const [start, setStart] = useState<Date[]>([]); useEffect(() => { publicHoliday?.forEach((holiday) => { const eventStartDate = holiday.startDate; const eventEndDate = holiday.endDate; const holidayDates = enumerateDaysBetweenDates(eventStartDate, eventEndDate); // 函数式更新拿到上一轮的最新状态,同时展开holidayDates打散元素 setStart(prev => [...prev, ...holidayDates]); }); }, [publicHoliday]);
内容的提问来源于stack exchange,提问作者Ammar ALSananni
相关产品推荐
相关产品推荐

