React范围滑块过滤数据报SetStateAction错误及分页筛选保活问题
问题修复方案
1. TypeScript 报错修复
报错核心原因有3个:
- 你给状态设值时写的是
minVal.toString/maxVal.toString,这里传入的是toString函数本身,不是函数执行后返回的字符串,TS检测到你给string类型的state传了函数类型值,才抛出类型不匹配错误,提示你需要调用这个表达式。 - 组件Props的TS类型写法错误,解构Props时类型标注要写在整个解构对象的外侧,不能拆分写在每个属性后面。
- 代码里
maxduration参数前面多打了一个多余的逗号,会导致后端无法正确识别请求参数。 - 原有代码的
setTimeout没传延迟时间,默认延迟为0,防抖效果几乎为0,会频繁触发请求,建议加300ms左右的防抖延迟。
修复后的核心代码片段:
// 先定义Props类型 type DurationFilterProps = { durMax: string; durMin: string; onChangeCallback: (filter: { param: string; value: string }) => void; } function DurationFilter({ durMax, durMin, onChangeCallback, }: DurationFilterProps) { // ...组件内部逻辑 const handleChange = (event: Event, newValue: number | number[]) => { const [minVal, maxVal] = Array.isArray(newValue) ? newValue : [newValue, newValue]; // 加()调用toString方法,拿到返回的字符串值 setMinDuration(minVal.toString()); setMaxDuration(maxVal.toString()); }; useEffect(() => { const timeOutId = setTimeout( // 删掉参数前多余的逗号 () => onChangeCallback({ param: 'maxduration', value: maxDuration }), 300 // 加防抖延迟 ); return () => clearTimeout(timeOutId); }, [maxDuration, onChangeCallback]); // ...minDuration的useEffect同理修正 }
额外注意:你现在给Slider传的是defaultValue,属于非受控组件写法,如果需要父组件传入的durMin/durMax更新时滑块同步变化,要改成value属性做受控绑定;另外parseInt解析空字符串/非法值时会返回NaN,建议加兜底值避免滑块渲染异常:
defaultValue={[parseInt(minDuration) || 0, parseInt(maxDuration) || 0]}
2. 切换分页保留筛选条件的方案
核心逻辑是不要把筛选条件只存在DurationFilter组件的本地state里:
- 把所有筛选参数(时长min/max、其他过滤条件)和分页参数,统一存储在筛选组件、分页组件共同的父组件中,也可以存在路由query参数、全局状态(Context、Redux、Zustand等)里。
- 不管是修改筛选条件还是切换分页,触发请求时都从统一存储位置读取全量过滤参数+分页参数再发请求,切分页时不要重置筛选值即可。
- 如果用路由参数存储筛选和分页状态,用户刷新页面也能保留当前查询条件,体验更好。
完整修正后代码
import React, { useEffect, useState } from 'react'; import { Box, Slider } from '@mui/material'; // 按你项目实际导入路径调整 type DurationFilterProps = { durMax: string; durMin: string; onChangeCallback: (filter: { param: string; value: string }) => void; } function DurationFilter({ durMax, durMin, onChangeCallback, }: DurationFilterProps) { const [maxDuration, setMaxDuration] = useState<string>(durMax); const [minDuration, setMinDuration] = useState<string>(durMin); const handleChange = (event: Event, newValue: number | number[]) => { const [minVal, maxVal] = Array.isArray(newValue) ? newValue : [newValue, newValue]; setMinDuration(minVal.toString()); setMaxDuration(maxVal.toString()); }; useEffect(() => { const timeOutId = setTimeout( () => onChangeCallback({ param: 'maxduration', value: maxDuration }), 300 ); return () => clearTimeout(timeOutId); }, [maxDuration, onChangeCallback]); useEffect(() => { const timeOutId = setTimeout( () => onChangeCallback({ param: 'minduration', value: minDuration }), 300 ); return () => clearTimeout(timeOutId); }, [minDuration, onChangeCallback]); return ( <Box> <Slider getAriaLabel={() => 'Duration range'} onChange={handleChange} defaultValue={[parseInt(minDuration) || 0, parseInt(maxDuration) || 0]} /> </Box> ); } export default DurationFilter;
内容的提问来源于stack exchange,提问作者Noobie
相关产品推荐
相关产品推荐

