I have a simple app that makes a connection to a sqlite database, reads results from that database, and displays them. Here is the app:
import React, { useEffect, useState } from 'react';
import { View, Text } from 'react-native'
import * as SQLite from "expo-sqlite";
import * as FileSystem from 'expo-file-system';
import { Asset } from 'expo-asset';
async function openDatabase() {
if (!(await FileSystem.getInfoAsync(FileSystem.documentDirectory + 'SQLite')).exists) {
await FileSystem.makeDirectoryAsync(FileSystem.documentDirectory + 'SQLite');
}
await FileSystem.downloadAsync(
Asset.fromModule(require('./assets/banana-dict.db')).uri,
FileSystem.documentDirectory + 'SQLite/banana-dict.db'
);
return SQLite.openDatabase('banana-dict.db');
}
export default function App() {
const [ dicts, setDicts ] = useState([]);
const [ db, setDb ] = useState({
transaction: () => {
return {
executeSql: () => {},
};
}});
const updateDicts = (a) => {
setDicts(
Object.fromEntries(a.map(({rowid, ...rest}) => [rowid, rest]))
);
}
const fetchDicts = () => {
console.log('fetch')
db.transaction((tx) => {
tx.executeSql(
`select rowid, * from dicts;`,
[],
(_, { rows: { _array } }) => { console.log(_array); updateDicts(_array); }
);
});
}
useEffect(() => {
openDatabase().then((value) => {
setDb(value);
fetchDicts();
});
}, []);
return (
<View style={{marginTop: 100}}>
<Text>Open App.js to start working on your app!</Text>
<Text>{JSON.stringify(dicts)}</Text>
</View>
);
}
banana-dict.db is a preexisting database I'm using for this app.
I've found that if I start the app and open it on my phone, the dicts state (ie, results of a query on the db) do not appear. However, if I press r in the console for a refresh, the results appear immediately.
Anyone know why this is?
When the app starts, the initial
dbvalue is set. The first effect batchessetDbandfetchDicts, sodb.transactionhas not been updated with the value of thesetDbcall. Because Expo has stateful refresh, thedbis no longer set as the initial value but has the result ofsetDb, sofetchDictsworks, and the results appear.One way to fix this would be to move
fetchDictsinto its own effect, and call it whendbchanges.