React Native+Back4App应用首次加载json.filter()无结果,刷新后正常
费用追踪应用首次加载过滤数据失败问题解决
问题背景
使用React Native和Back4App(Parse)开发费用追踪应用,需要从Parse数据库的Transactions类中获取数据,并按username字段过滤。数据库数据示例:
[ { "amount": -350, "objectId": "hzXdXRj8jf", "type": "Expense", "username": "james", }, { "amount": -200, "objectId": "r2uDmSZ666", "type": "Expense", "username": "james", }, { "amount": 2000, "objectId": "FBEGubpwNn", "type": "Income", "username": "sheldon", }, { "amount": -500, "objectId": "oYam0dUOxu", "type": "Expense", "username": "sheldon", }, ]
当前问题:首次加载或重启应用时,过滤后的结果为空数组;手动刷新FlatList后,能返回正确的过滤结果。尝试用parseQuery.contains('username', username)做后端过滤也存在同样问题,而不做过滤直接加载全部数据时首次加载正常,但会返回所有用户数据,不符合需求。
问题原因
核心问题是异步操作顺序错误:在readTransactions函数中调用getCurrentUser()(异步函数)时没有加await,导致执行数据库查询和前端过滤时,username状态还未被更新(仍为初始值),因此过滤条件不匹配,返回空数组。手动刷新时,username已经在上一次操作中被设置完成,所以过滤逻辑能正常工作。
修复方案
方案1:修正前端过滤逻辑
确保获取到当前用户名后再执行查询和过滤,同时优化Parse对象的处理方式(无需转成JSON再过滤):
const getCurrentUser = async () => { const user = await Parse.User.currentAsync() if(user !== null) { return user.get('username') } else { Alert.alert("Error!", "Cannot fetch username") return null } } const readTransactions = async () => { setLoading(true) // 等待获取当前用户名完成 const currentUsername = await getCurrentUser() if (!currentUsername) { setLoading(false) return } const parseQuery = new Parse.Query("Transactions") try { let results = await parseQuery.find() // 直接使用Parse对象的get方法访问字段,无需转JSON const filteredTransactions = results.filter(item => item.get('username') === currentUsername) // 转成普通JSON对象存入状态(如果需要) const jsonTransactions = filteredTransactions.map(item => item.toJSON()) console.log(jsonTransactions) setTransactions(jsonTransactions) } catch (error) { console.error('获取交易数据失败:', error) } finally { // 无论成功失败,都更新加载状态 setLoading(false) setRefresh(false) } }
方案2:正确使用Parse后端过滤(推荐)
后端过滤能减少前端数据传输量,提升性能。之前使用contains是错误的,应该用equalTo做精确匹配,同时确保获取到用户信息后再构建查询:
const readTransactions = async () => { setLoading(true) const user = await Parse.User.currentAsync() if (!user) { Alert.alert("Error!", "Cannot fetch current user") setLoading(false) return } const currentUsername = user.get('username') const parseQuery = new Parse.Query("Transactions") // 用equalTo精确匹配username字段 parseQuery.equalTo('username', currentUsername) try { let results = await parseQuery.find() const jsonTransactions = results.map(item => item.toJSON()) console.log(jsonTransactions) setTransactions(jsonTransactions) } catch (error) { console.error('获取交易数据失败:', error) } finally { setLoading(false) setRefresh(false) } }
额外优化建议
- 可以去掉单独的
getCurrentUser函数,直接在readTransactions中获取用户信息,减少异步嵌套 - 使用
finally块统一管理加载状态的重置,避免遗漏 - 依赖异步操作返回的直接结果(如
currentUsername),而不是React状态值,因为状态更新是异步的,可能存在延迟
内容的提问来源于stack exchange,提问作者san
相关产品推荐
相关产品推荐

