React Native中useEffect内调用setGeofence导致应用崩溃
解决React Native中setState设置SQLite查询结果崩溃的问题
问题分析
你遇到的崩溃核心原因是results.rows._array并非纯JavaScript对象数组,而是SQLite库返回的内部结构对象——这类对象可能包含循环引用、不可序列化的隐藏属性,或者部分字段类型(比如state字段在SQLite中实际存储为数字0/1而非布尔值)与组件渲染预期不符。而传入普通字符串时,因为是基础类型,React能正常处理状态更新,所以不会触发崩溃。
解决方案
1. 转换为纯JS对象数组
通过深拷贝把SQLite返回的内部对象转换成普通JS对象,避免React处理非序列化数据:
tx.executeSql("select * from geofence", [], (tx, results) => { // 深拷贝剥离SQLite内部属性 const pureGeofenceData = JSON.parse(JSON.stringify(results.rows._array)); setGeofence(pureGeofenceData); console.log("egeo" + pureGeofenceData.length); });
2. 手动映射并修正字段类型
如果深拷贝后仍有问题,手动遍历数组,针对性转换类型不匹配的字段:
tx.executeSql("select * from geofence", [], (tx, results) => { const formattedData = results.rows._array.map(item => ({ ...item, // 把SQLite返回的数字/字符串统一转为布尔值 state: item.state === 1 || item.state === "true" })); setGeofence(formattedData); console.log("egeo" + formattedData.length); });
3. 确保事务执行顺序(可选)
虽然同事务内SQLite会按顺序执行语句,但用Promise封装事务能更稳妥地保证创建表完成后再执行查询:
useEffect(() => { const initDb = async () => { // 先确保表创建完成 await new Promise(resolve => { db.transaction(tx => { tx.executeSql( "create table if not exists geofence (id text primary key not null, lat text, lng text, note text, radius real, state boolean );", [], () => resolve() ); }); }); // 再执行查询并更新状态 await new Promise(resolve => { db.transaction(tx => { tx.executeSql("select * from geofence", [], (tx, results) => { const formattedData = results.rows._array.map(item => ({ ...item, state: Boolean(item.state) })); setGeofence(formattedData); console.log("egeo" + formattedData.length); resolve(); }); }); }); }; initDb(); }, []);
内容的提问来源于stack exchange,提问作者vatsal mandloi
相关产品推荐
相关产品推荐

