Next.js 10.0.5中使用浅路由(Shallow Routing)更新路由后router.query无法获取最新查询字符串的问题
嘿,我之前在Next.js 10里也踩过这个浅路由的坑!问题出在这几个地方,我帮你捋一捋:
核心问题:闭包陷阱 + 浅路由的渲染特性
你的selectFilter函数被包裹在_.debounce里,又通过useCallback用空依赖数组缓存了下来——这意味着这个debounce函数从组件挂载开始,就一直引用着第一次渲染时的router.query值(也就是初始的undefined),不管你之后怎么更新路由,它拿到的始终是旧值,自然每次都进入else分支。
另外,Next.js的浅路由更新不会触发组件重新渲染,所以router.query不会自动同步到组件的闭包里,必须主动获取最新值。
修复方案
我调整了你的代码,主要解决闭包问题,同时优化浅路由的使用:
const NumberFilter = ({ filter }) => { const router = useRouter() const [value, setValue] = useState('') // 用useRef保存debounce函数,避免每次渲染重置延迟 const selectFilterRef = useRef(_.debounce((inputValue) => { // 每次执行时都获取最新的路由参数,避开闭包陷阱 const currentQuery = { ...router.query }; const filterSearch = `${filter.id}-${inputValue}-${inputValue}`; let filters; if (inputValue !== null) { const lastQsf = currentQuery['filters']; if (Array.isArray(lastQsf)) { filters = [...lastQsf, filterSearch]; } else if (typeof lastQsf === 'string') { filters = [lastQsf, filterSearch]; } else { filters = [filterSearch]; } } router.push( { pathname: router.pathname, query: { ...currentQuery, filters } }, undefined, { shallow: true } ); }, 1000)); const handleChange = useCallback((inputValue) => { selectFilterRef.current(inputValue); }, []); // 可选:监听路由参数变化,方便后续处理(比如回显筛选值) useEffect(() => { console.log('最新的查询参数:', router.query); }, [router.query]); return ( <NumberFormat placeHolder={filter.label} onValueChange={(values)=> { setValue(values.value); handleChange(values.value); }} displayType={'number'} value={value} thousandSeparator={true} className="form-control c-form-builder-input mt-15" /> ) }
关键改动说明
- 用
useRef保存debounce函数:这样组件重新渲染时不会重新创建debounce实例,避免输入时频繁重置延迟时间,同时保证每次执行时能拿到最新的router引用。 - 在debounce内部获取最新
router.query:直接从router上取当前值,彻底避开闭包带来的旧值问题。 - 添加
useEffect监听router.query:如果之后需要根据最新的查询参数更新组件状态(比如回显已选的筛选值),这个监听能帮你及时响应路由变化。
这样修改后,你应该就能正常更新查询字符串,并且后续能获取到最新的router.query值了!
内容的提问来源于stack exchange,提问作者Ghazaleh Javaheri
相关产品推荐
相关产品推荐

