javascriptreactjsreact-nativereact-native-sqlite-storage

Confusion on async and promise. React Native


I am new to React-Native and JS and I am really weak on the understanding on how async/promise/await works. What I am trying to implement is an async function (using react-native-sqlite-storage), "runDemo" in file "SQLData.js", that would be called in "Apps.js" and the loaded data would then be passed as a prop to be rendered in a FlatList.

Apps.js

import React from 'react';
import CustomList from './components/FlatList';
import SQLData from './components/SQLData';

 
//This uses functional instead of class component
let data;
export default function App() {

  
  async function fetchData() {
    data = await SQLData.runDemo();
    return data;
  }
  return(
    <CustomList data={fetchData()}/>
  );
};

SQLData.js

Gets data from users.db

export async function runDemo() {
  
  try {
    const db = await new Promise((resolve, reject) => {
      const db = SQLite.openDatabase(
        { name: 'users.db', createFromLocation: 1 },
        () => resolve(db),
        reject
      )
    })

    const results = await new Promise((resolve, reject) => {
      db.transaction(tx => {
        tx.executeSql(
          'SELECT * FROM users',
          [],
          (tx, results) => resolve(results),
          reject
        )
      })
    })

    const localArray = []
    for (let i = 0; i < results.rows.length; i++) {
      localArray.push(results.rows.item(i))
    }
    return localArray
  } catch (e) {
    console.log('SQL Error: ', e)
    return false
  }
}

I understand that I am creating an async function runDemo() that will return a promise but other than that I'm unsure of what I'm suppose to do in Apps.js!

The error I am receiving is Invariant Violation: Tried to get frame for out of range index NaN. I believe that I am getting this error because I am not properly calling runDemo() in Apps.js and it is returning an undefined object as props into CustomList


Solution

  • You can useEffect hook to run the side effects such as fetching data. Once you fetch the data you can add that to the state.

    import React, { useEffect, useState } from 'react'; 
    export default function App() {
    
        [someData, setSomeData] = useState();
    
        useEffect(() => {
            (async () => {
                const data = await SQLData.runDemo();
                setSomeData(data);
            })()
        }, [setSomeData]) // add any additional dependencies
    
    
        return (someData ? <CustomList data={someData} /> : null);
    };