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.