React按工作地点筛选JSON职位数据时URL参数不更新问题排查
问题背景
我正在为当前开发的项目构建筛选功能,需要解析后端API返回的JSON数据,根据工作地点字段筛选职位帖子并完成展示。
原问题代码
useEffect(async () => { let condition = await getJobs(); switch (jobCondition) { case 'On-site': condition.filter((condition.jobLocation === 'in_person')); break; case 'Remote': condition.filter((condition.jobLocation === 'remote')); break; case 'Hybrid': condition.filter((condition.jobLocation === 'hybrid')); break; default: condition = null; } if (condition != null) { const params = new URLSearchParams({ jobs: jobFilter || null, location: locationFilter || null, since: datePosted || null, conditions: condition.data, }); history.push({ pathname: '/', search: `${params.toString()}` }); return; } const params = new URLSearchParams({ jobs: jobFilter || null, location: locationFilter || null, since: null, conditions: null, }); history.push({ pathname: '/', search: `${params.toString()}` }); }, [jobCondition]);
上述代码运行存在明显异常,执行后URL参数完全没有发生变化,无法实现预期的筛选跳转效果。
问题原因
代码存在4个核心错误,直接导致逻辑中断、筛选失效:
useEffect不支持直接传入async函数作为回调。useEffect要求回调返回值为清理函数或undefined,async函数默认返回Promise对象,会导致React无法正确处理副作用执行时序,容易引发执行异常。- 对
Array.filter()的用法完全错误:filter方法接收的入参必须是判断函数,原代码传入的是一个布尔表达式(condition.jobLocation === 'xxx'),不是函数,调用时会直接抛出类型错误;filter不会修改原数组,执行后会返回全新的筛选后数组,原代码没有接收filter的返回值,即使语法正确,筛选结果也不会被保存。
- 数据结构理解错误:从后续代码
condition.data可以判断,await getJobs()返回的是接口响应对象,职位列表存储在响应的data字段中,原代码直接在响应对象(非数组)上调用filter方法,会直接触发「filter不是一个函数」的报错,导致后续路由跳转逻辑完全终止,这也是URL参数完全没有变化的直接原因。 - 默认分支逻辑错误:当没有匹配到筛选条件时,原代码直接将
condition置为null,会导致无筛选条件时参数构造逻辑不符合预期。
修复方案
修复后的代码如下:
useEffect(() => { // 不要直接给useEffect传async回调,在内部定义异步函数执行 const fetchAndFilterJobs = async () => { const res = await getJobs(); // 先从响应中取出职位数组 const jobList = res.data; let filteredJobs = jobList; switch (jobCondition) { case 'On-site': // 传入正确的筛选回调,接收返回的新数组 filteredJobs = jobList.filter(item => item.jobLocation === 'in_person'); break; case 'Remote': filteredJobs = jobList.filter(item => item.jobLocation === 'remote'); break; case 'Hybrid': filteredJobs = jobList.filter(item => item.jobLocation === 'hybrid'); break; default: // 默认不做筛选,保留全量列表 filteredJobs = jobList; } const params = new URLSearchParams({ jobs: jobFilter || null, location: locationFilter || null, since: jobCondition ? datePosted || null : null, conditions: jobCondition ? JSON.stringify(filteredJobs) : null }); history.push({ pathname: '/', search: params.toString() }); }; fetchAndFilterJobs(); }, [jobCondition, jobFilter, locationFilter, datePosted, history]);
注意:URLSearchParams不支持直接传入对象/数组作为参数值,如果需要把筛选后的职位列表放到URL参数中,需要先序列化为字符串格式,否则会被自动转成[object Object]导致参数失效。
内容的提问来源于stack exchange,提问作者Yuradzi
相关产品推荐
相关产品推荐

