使用useState实现嵌套数组训练计划滑块及回退按钮问题排查
训练计划滑块组件回退功能修复方案
问题排查
你的代码里回退按钮失效主要有两个核心问题:
- 拼写错误:
currentCycle.exercises.lengh-1里的lengh是笔误,正确拼写是length,导致无法正确计算上一个训练组的最后一个动作索引。 - 逻辑漏洞:当
innerIndex为0时,直接执行setOuterIndex(outerIndex-1),虽然后台按钮会被禁用,但函数内未做防御性检查;同时,回退到上一个训练组时,错误地使用了当前训练组的动作列表长度,而非上一个训练组的。
另外,边界判断逻辑可以简化,避免冗余的三元表达式。
修复后的完整代码
import React from 'react' import { useState } from 'react'; import { useLocation } from 'react-router-dom' const Workout = () => { const { state } = useLocation(); const workout = state; const [ outerIndex, setOuterIndex ] = useState(0); const [ innerIndex, setInnerIndex ] = useState(0); const currentCycle = workout.cycles[outerIndex]; const currentExercise = currentCycle.exercises[innerIndex]; // 简化边界判断逻辑,语义化命名 const isLastItem = innerIndex === currentCycle.exercises.length - 1 && outerIndex === workout.cycles.length - 1; const isFirstItem = innerIndex === 0 && outerIndex === 0; const nextIndex = () => { if (innerIndex === currentCycle.exercises.length - 1) { // 使用函数式更新避免异步state导致的索引偏差 setOuterIndex(prev => prev + 1); setInnerIndex(0); } else { setInnerIndex(prev => prev + 1); } } const prevIndex = () => { // 防御性检查:已经是第一个元素时直接返回 if (isFirstItem) return; if (innerIndex === 0) { // 回退到上一个cycle的最后一个exercise const prevCycle = workout.cycles[outerIndex - 1]; setOuterIndex(prev => prev - 1); setInnerIndex(prevCycle.exercises.length - 1); } else { setInnerIndex(prev => prev - 1); } } return ( <section id="workout-container"> <h3>{workout.name}</h3> <aside>Orientações:{workout.workoutObs}</aside> <button onClick={prevIndex} disabled={isFirstItem}>prev</button> <button onClick={nextIndex} disabled={isLastItem}>next</button> <div className='cycle-item'> <h4>Ciclo {outerIndex+1} - {currentCycle.series}x</h4> <div className='exercise-item'> <p>{currentExercise.name}</p> <p>reps.:{currentExercise.reps}</p> </div> <p>{currentCycle.cycleObs}</p> </div> </section> ) } export default Workout;
关键修改点说明
- 修正拼写错误:将
lengh改为length,确保能正确获取动作列表的长度值。 - 函数式state更新:使用
setState(prev => prev + 1)的形式更新索引,避免因React state异步特性导致的连续点击时索引计算错误。 - 回退逻辑修复:回退到上一个训练组时,先获取目标训练组的动作列表,再将
innerIndex设为该列表的最后一个索引。 - 语义化边界判断:将原
maxLimit/minLimit重命名为isLastItem/isFirstItem,用全等判断简化逻辑,提升可读性。 - 防御性检查:在
prevIndex函数开头增加边界判断,避免无效的索引操作。
内容的提问来源于stack exchange,提问作者AgstAngelo
相关产品推荐
相关产品推荐

