Expo应用中.filter方法筛选用户列表无返回结果问题排查
Expo+AWS应用用户列表筛选后为空问题修复
问题背景
基于Expo开发、后端依托AWS搭建的社交类应用,需要在拉取用户列表的fetchUsers函数中添加筛选逻辑,过滤掉已与当前认证用户完成匹配的用户,避免用户重复滑动浏览已匹配对象,但调用fetchedUsers.filter方法后未返回任何用户卡片。
已实现的匹配拉取逻辑
首先实现了fetchMatches函数,用于拉取所有和当前认证用户达成匹配的用户数据,代码如下:
useEffect(() => { if (!me) { return; } fetchMatches(); }, [me]); const fetchMatches = async () => { const result = await DataStore.query(Match, match => match .isMatch('eq', true) .or(match => match.matchUser1Id('eq', me.id).matchUser2Id('eq', me.id)) ); setMatches(result); console.warn(result); }
已实现的用户列表拉取逻辑
后续实现fetchUsers函数,原逻辑为基于已获取的匹配列表,提取匹配关系中的用户ID,和拉取到的全量用户ID做比对,排除ID重合的已匹配用户,代码如下:
useEffect(() => { if(!isUserLoading && user) { fetchUsers(); } }, [me, matches, user]); const fetchUsers = async () => { let fetchedUsers = await DataStore.query(User); setUsers(fetchedUsers.filter(user => { matches.filter(match => match.matchUser1Id !== user.id && match.matchUser2Id !== user.id ) })); }
问题现象
- 为
fetchedUsers添加上述filter筛选逻辑后,首页未渲染任何用户卡片 - 移除filter逻辑、直接调用
setUsers(fetchedUsers)时,可以正常返回并渲染数据库中的全量用户列表 - 控制台未出现未处理的Promise报错或其他类型错误,仅存在筛选后列表不渲染的问题
根因分析
问题由3个代码逻辑错误共同导致:
- 外层filter回调缺少return语句:
fetchedUsers.filter传入的回调使用大括号包裹函数体,但没有写显式return。箭头函数使用大括号包裹函数体时不会自动返回执行结果,默认返回undefined(falsy值),因此所有用户都被判定为不需要保留,直接返回空数组,这是列表为空的核心原因。 - 筛选判断逻辑错误:就算补上return语句,内层使用
matches.filter也无法得到正确的布尔判断结果。Array.filter返回值始终是数组,而JS中无论数组是否为空,转布尔值时均为truthy,无法正确判定「当前用户是否在已匹配列表中」。 - Match查询条件逻辑错误:DataStore查询语法中,
or回调内链式调用条件默认是且关系,原代码写的.or(match => match.matchUser1Id('eq', me.id).matchUser2Id('eq', me.id))实际查询的是「匹配记录中user1是me且user2也是me」的无效数据,根本拉取不到正确的已匹配列表。
修复方案
- 首先修复
fetchMatches的查询条件,正确拉取当前用户的所有已匹配记录:
const fetchMatches = async () => { const result = await DataStore.query(Match, match => match .isMatch('eq', true) .or(match => match.matchUser1Id('eq', me.id).or(innerMatch => innerMatch.matchUser2Id('eq', me.id)) ) ); setMatches(result); console.warn(result); }
- 重写
fetchUsers的筛选逻辑,做好空值兜底,同时过滤当前登录用户本人避免自滑:
const fetchUsers = async () => { let fetchedUsers = await DataStore.query(User); // 兜底处理matches未初始化的场景,提取所有匹配关联的用户ID存入Set提升查询性能 const matchedUserIds = new Set( (matches || []).flatMap(match => [match.matchUser1Id, match.matchUser2Id]) ); // 把当前登录用户自己加入过滤集合,避免用户滑到自己的卡片 matchedUserIds.add(me.id); setUsers( fetchedUsers.filter(user => !matchedUserIds.has(user.id)) ); }
优化说明:使用Set存储需要过滤的用户ID,单次ID判断的时间复杂度为O(1),相比每次遍历matches数组做判断,在匹配记录较多时性能优势明显。
内容的提问来源于stack exchange,提问作者azoth820
相关产品推荐
相关产品推荐

