React Native 应用程序的 expo-sqlite 回调直到应用程序刷新才执行

React Native app's expo-sqlite callback not executed until app refresh

我有一个简单的应用程序,可以连接到 sqlite 数据库,从该数据库读取结果并显示它们。这是应用程序:


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 是我用于此应用程序的预先存在的数据库。 我发现如果我启动应用程序并在我的 phone 上打开它,dicts 状态(即数据库查询的结果)不会出现。但是,如果我在控制台中按 r 进行刷新,结果会立即出现。 有人知道这是为什么吗?

当应用程序启动时,会设置初始 db 值。第一个效果批处理 setDbfetchDicts,因此 db.transaction 尚未更新为 setDb 调用的值。因为 Expo 有状态刷新,所以 db 不再设置为初始值,而是有 setDb 的结果,所以 fetchDicts 工作,结果出现。

解决此问题的一种方法是将 fetchDicts 移动到它自己的效果中,并在 db 更改时调用它。

useEffect(() => {
  openDatabase().then((value) => {
    setDb(value);
  });
}, []);

useEffect(() => {
  fetchDicts(); // will do nothing until db connection is open
}, [db]);