使用useState更新时页面整体重载问题求助
问题排查:点击时间调整按钮后页面重载
我要做一个可通过点击箭头设置时间的组件(效果类似带上下箭头的时间选择器),用useState实现了TSX组件,但每次点击增减时间的按钮,操作触发一次后整个页面就会重载。试过传递函数、调整useEffect、挂载到根元素等方法,问题仍未解决,请求排查原因。
组件代码如下:
type Props = { placeholder?: string | number, time: number, } export function PetTimeSet(props: Props) { const {placeholder, time} = props // const [toggleClass, setToggleClass] = useState('inactive'); const [currentTime, setCurrentTime] = useState(time) const getPadTime = (t:number) => t.toString().padStart(2, '0') const hours = getPadTime(Math.floor(currentTime / 60)) // @ts-ignore const minutes = getPadTime(currentTime - hours * 60) useEffect(() => { if (Math.floor(currentTime / 60) >= 24) { setCurrentTime(0) } }, [currentTime]) const handleTimeUncrease = () => setCurrentTime(prevTime => prevTime + 5) const handleTimeDecrease = () => setCurrentTime(prevTime => prevTime - 5) return ( <div // onChange={() => setToggleClass('active')} //tslint:disable-next-line:typedef // onClick={() => {setToggleClass('active')}} className={`PetTimeSet `}> <span className="PetTimeSet-index">{placeholder}</span> <span className="PetTimeSet-choice"> <button className="time-decrease"> <img src={arrow} alt="decrease" onClick={handleTimeDecrease} /> </button> <span className="PetTimeSet-time">{`${hours}:${minutes}`}</span> <button className="time-uncrease" onClick={handleTimeUncrease}> <img src={arrow} alt="uncrease" /> </button> </span> </div> ) }
问题原因与解决方法
核心原因:HTML中的
<button>默认类型是submit,如果你的组件被嵌套在<form>标签内部,点击按钮会触发表单的默认提交行为,直接导致页面刷新。最直接的解决方法:给按钮明确设置
type="button",覆盖默认的submit类型:
<button type="button" className="time-decrease"> <img src={arrow} alt="decrease" onClick={handleTimeDecrease} /> </button> <button type="button" className="time-uncrease" onClick={handleTimeUncrease}> <img src={arrow} alt="uncrease" /> </button>
- 备选解决方法:如果不想修改按钮类型,可以在点击事件中阻止默认行为,修改函数如下:
const handleTimeUncrease = (e: React.MouseEvent<HTMLButtonElement>) => { e.preventDefault(); setCurrentTime(prevTime => prevTime + 5); }; const handleTimeDecrease = (e: React.MouseEvent<HTMLButtonElement>) => { e.preventDefault(); setCurrentTime(prevTime => prevTime - 5); };
额外优化建议
- 去掉
minutes计算里的@ts-ignore,因为hours是字符串,需要转成数字再计算:
const minutes = getPadTime(currentTime - Number(hours) * 60);
- 补充时间减少到负数的处理逻辑,比如当
currentTime -5 < 0时,设置为0或者循环到23:55,避免出现负时间。
内容的提问来源于stack exchange,提问作者Dmitr Zar
相关产品推荐
相关产品推荐

