I tried to fetch data from an embedded sqlite db and displayed it in list format. The fetchData() function is working, with correct returned result. However, when I used setState() to update the state, react did not re-render. Next I tried to setState() with array [‘a’,’b’,’c’] at componentDidMount(). React did re-render and showed a, b, c.
import React from 'react'; import sqlite3 from 'sqlite3'; type MyProps = { }; type MyState = { data: Array<string> }; class App extends React.Component<MyProps, MyState>{ constructor(props) { super(props); this.state = { data: [] }; } async fetchData(){ var db = new sqlite3.Database({$DB_PATH}); var res: string[] = []; await db.each('select * from table', [], (err, row) => { //selecting 10 rows from table if (err) { throw err; } res.push(row.name); }); db.close(); console.log(this.state.data) //array length = 0 this.setState({data: res}) console.log(this.state.data) //array length = 10 } async componentDidMount() { await this.fetchData(); } render() { return ( <div> <ul> {this.state.data.map(el => ( <li> {el} </li> ))} </ul> </div> ); } } export default App;
Advertisement
Answer
Because of db.each
won’t return a Promise
so that you cannot reach result by ‘await’ statement.
Refer to the APIs, you’ll need to this:
each(sql: string, params: any, callback?: (this: Statement, err: Error | null, row: any) => void, complete?: (err: Error | null, count: number) => void): this;
so, you should access the result in the complete
callback, code like so:
async fetchData() { const db = new sqlite3.Database({ $DB_PATH }); const res: string[] = []; await db.each('select * from table', [], (err, row) => { // selecting 10 rows from table if (err) { throw err; } res.push(row.name); }, () => { console.log(this.state.data) // array length = 0 this.setState({ data: res }) console.log(this.state.data) // array length = 10 db.close(); }); }
Hope it will be helpful.
Besides, you can also have a try with Statement#all([param, ...], [callback])
function which is a better than each
.