React native function return nothing - sqlite

I'm trying to do something simple here - connect to a sqlite database and return the number of records. In the code below I can output the len variable with console.log, but nothing gets returned. Am I missing something obvious? Thanks.
const db = SQLite.openDatabase({ name: 'favorites.db' });
export default class PlayerScreen extends React.Component {
fetch(){
console.log('fetching data from database');
var query = "SELECT * FROM items";
var params = [];
db.transaction((tx) => {
tx.executeSql(query,params, (tx, results) => {
var len = results.rows.length;
return len;
}, function(){
console.log('Profile: Something went wrong');
});
});
}
render() {
return <Text>{this.fetch()}</Text>
}
}

A lot of things are wrong here. Fetch is an asynchronous concept and React rendering is synchronous. You cannot use fetch or anything asynchronously inside the render method.
So, what should you do instead?
First, do the fetch in the componentDidMount of the component.
Also set an initial state in componentWillMount
componentWillMount() {
this.state = { length: 0 };
}
componentDidMount() {
// I use call here to make sure this.fetch gets the this context
this.fetch.call(this);
}
Secondly, attach the results to the innerState of the component in your fetch method
fetch() {
var query = "SELECT * FROM items";
var params = [];
db.transaction((tx) => {
tx.executeSql(query,params, (tx, results) => {
var len = results.rows.length;
// this.setState will trigger a re-render of the component
this.setState({ length: len });
}, function(){
console.log('Profile: Something went wrong');
});
});
}
Now, in the render method, you can use this.state.length to render the value.
render() {
return <Text>{this.state.length}</Text>
}
Hope this helps you out

Just putting this here for any other poor souls who this may help since this thread was the top result for me:
SQL isn't case sensitive, but React is. All my variables were lowercase, but my SQL tables used uppercase. So "SELECT key" actually returned "Key".
Therefore, rewriting the SQL query as "SELECT key as key" fixed it for me, since the first "key" isn't case sensitive, but the second one is.
Alternatively, just change the database headers to whatever case you'll be using in your program.

Related

useSwr fetch with filter query params

I have a component which displays a list of sources. Users will be able to filter this list with search keywords.
I have a state called searchKeyword which holds the input value.
I need to make a request when user clicks on search.
const { data, error } = useSWR(`source-requests/favorite?keyword=${searchKeyword}`);
const submitSearch = (e) => {
e.preventDefault();
mutate(source-requests/favorite?keyword=${searchKeyword});
};
This makes call on every keystroke. How do I prevent this.
I believe what you are looking for is a debounce function.
You could implement your own with something like this:
const debounce = (func, wait) => {
let timeout
return (...args) => {
clearTimeout(timeout)
timeout = setTimeout(() => {
func(args)
}, wait)
}
}
All together it could look something like this:
const [searchKeyword, setSearchKeyword] = useState(null)
const { data, error } = useSWR(
searchKeyword
? `source-requests/favorite?keyword=${searchKeyword}`
: null
);
const submitSearch = debounce(setSearchKeyword, 500);
Alternatively, you could use a more featureful debounce function from a library such as lodash or underscore.

React Native state console.log

I am using firebase for my app and the data i read i want to put that in state to use it in different places.
it kinda works but when i want to console.log the state it updates like 30 times a second, am i doing something wrong?
this is my code
const db = firebase.firestore();
const [PBS1Detail, setPBS1Detail] = useState();
db.collection('Track').get().then((snapshot) => {
snapshot.docs.forEach(doc => {
renderTracks(doc)
}
)
});
const renderTracks = (doc) => {
let data = doc.data().data[0].Module;
return setPBS1Detail(data);
}
console.log(PBS1Detail)
i already tried to store it in a variable instead of state but thats not working for me, i can't get the variable from the function global
i am a noob i get it xd
You don't need a return statement when setting state. Also, it looks like you're performing some async function which means that when your component renders for the first time, PBS1Detail will be undefined since the db is a pending Promise.
You could/should put your async functions in useEffect hook:
useEffect(()=> {
db.collection('Track').get().then((snapshot) => {
snapshot.docs.forEach(doc => {
renderTracks(doc)
}
)
});
}, [])
const renderTracks = (doc) => {
let data = doc.data().data[0].Module;
setPBS1Detail(data);
}
Finally, your renderTracks function doesn't seem correct as it appears you're looping over docs and resetting your state each time.
Instead, maybe consider having an array for PBS1Detail
const [PBS1Detail, setPBS1Detail] = useState([]);
Then modify your async call:
useEffect(()=> {
db.collection('Track').get().then((snapshot) => {
let results = []
snapshot.docs.forEach(doc => {
results.push(renderTracks(doc))
}
)
setPBS1Detail(results)
});
}, [])
const renderTracks = (doc) => {
return doc.data().data[0].Module;
}
This way you're only setting state once and thus avoiding unnecessary re-renders and you're saving all of your docs instead of overwriting them.

Add an attribute to every item in a DynamoDB table with millions of items

I am pretty new to AWS, but I need to add an attribute (and set the value to something) to every single item in a DynamoDB table.
I'm trying to write a generic script that will be able to do this to any table passed into it.
After a little bit of digging, it looks like I should be able to do this just by doing a scan of the table, getting the items, and then updating every single item.
My questions are:
(1) Does this seem like a reasonable approach?
(2) Is there an easier / better way to do this automatically? (a table-wide addition of an attribute to every item in the table?)
Yes it sounds reasonable, not ideal, but reasonable
Sure, there is always a better way, but this is an easy way, Here is a snippet I ran as a local JS file...
const AWS = require('aws-sdk');
const dynamoDb = new AWS.DynamoDB.DocumentClient({
region:'us-east-1'
});
async function main(event, context) {
let tableContents;
try{
//get items from dynamo
const params = {
TableName: `${YOUR_TABLE_NAME}`,
};
tableContents = await scanDB(params);
}catch(err){
console.log(err);
return err;
}
let calls = [];
tableContents.forEach(function(value){
let params = {
ExpressionAttributeValues: {
":newAttribute": false,
},
Key: {
"indexKey": value.indexKey
},
TableName: `${YOUR_TABLE_NAME}`,
UpdateExpression: "SET newAttribute = :newAttribute",
};
calls.push(dynamoDb.update(params).promise());
});
let response;
try{
response = await Promise.all(calls);
}catch(err){
console.log(err);
}
return response;
}
async function scanDB(params) {
let dynamoContents = [];
let items;
do{
items = await dynamoDb.scan(params).promise();
items.Items.forEach((item) => dynamoContents.push(item));
params.ExclusiveStartKey = items.LastEvaluatedKey;
}while(typeof items.LastEvaluatedKey != "undefined");
return dynamoContents;
};
main();
Good luck!

How to save resulted values from firestore into a variable and use it on various components and states in Vue

I'm looking for a way to save the results received from a firestore collection and use it on a variable and reuse the save it to data() and reuse it.
I'm unsure how to save the results from a async function into a variable.
Please help me with this guys
Here is my code.
import firebase from "firebase";
export default{
data() {
return {
uid: firebase.auth().currentUser.uid,
teamLead: ""
};
},
created() {
db.collection("users").onSnapshot(users => {
users.docChanges().forEach(user => {
if (this.uid == user.doc.id) {
this.teamLead = user.doc.data().teamLead
}
});
});
console.log(this.teamLead)
In this code I would like to have the value of teamLead saved into the data() function. How do I do that?
It's a crazy idea to read all user from db. Instead of you can retrieve user by id.
Don't use "this" inside callbacks or lambda.
You have to understand order of execution of async programs. See my comments.
[]
export default{
data() {
return {
teamLead: ""
};
},
created() {
let self = this
db.collection("users").doc(firebase.auth().currentUser.uid).get().then(function(doc) {
if (doc.exists) {
self.teamLead = doc.data().teamLead
console.log(self.teamLead)//<-- this log will executed after firestore return any data
}
});
console.log(this.teamLead)//<-- this log will executed before firestore return any data

Google Translate API and Firebase Firestore are killing each other

We're trying to write a Google Cloud Function that gets a translation from Google Translate API, and then write the results to our Firebase Firestore database. Each works alone, but together nothing works. In other words, we can get a translation from Google Translate. We can write data to Firestore. But if we try to do both, we don't get a translation back from Google Translate, and nothing is written to Firebase. We get no error messages. We've tried the code with async await and with promises. Here's the code with promises:
exports.Google_EStranslateEN = functions.firestore.document('Users/{userID}/Spanish/Translation_Request').onUpdate((change, context) => {
if (change.after.data().word != undefined) {
const {Translate} = require('#google-cloud/translate');
const projectId = 'myProject-cd99d';
const translate = new Translate({
projectId: projectId,
});
// The text to translate
const text = change.after.data().word;
// The target language
const target = 'en';
let translationArray = []; // clear translation array
translate.translate(text, target)
.then(results => {
translation = results[0];
translationArray.push(translation);
try {
// write translation to dictionary
admin.firestore().collection('Dictionaries').doc('Spanish').collection('Words').doc(text).collection('Translations').doc('English').set({
'translationArray': translationArray,
'language': 'en',
'longLanguage': 'English'
})
.then(function() {
console.log("Translation written");
})
.catch(function(error) {
console.error(error);
});
} catch (error) {
console.error(error);
}
})
.catch(error => {
console.error('ERROR:', error);
});
}
});
Here's the same code with async await:
exports.Google_EStranslateEN = functions.firestore.document('Users/{userID}/Spanish/Translation_Request').onUpdate((change, context) => { // triggers when browser writes a request word to the database
if (change.after.data().word != undefined) {
async function getTranslation() {
try {
let translationArray = []; // clear translation array
const {Translate} = require('#google-cloud/translate');
const projectId = 'myProject-cd99d';
const translate = new Translate({
projectId: projectId,
});
// The text to translate
const text = change.after.data().word;
const options = {
to: 'en',
from: 'es',
format: 'text'
}
let [translations] = await translate.translate(text, options);
translations = Array.isArray(translations) ? translations : [translations]; // If translations is an array, leave it alone; if not, put it in an array
translationArray.push(translations[0]);
await admin.firestore().collection('Dictionaries').doc('Spanish').collection('Words').doc(text).collection('Translations').doc('English').set({
'translationArray': translationArray,
'language': 'en',
'longLanguage': 'English'
})
.then(function() {
console.log("Translation written");
})
.catch(function(error) {
console.error(error);
});
// };
} catch (error) {
console.error(error);
}
} // close getTranslation
getTranslation();
}
});
You're not returning a promise that's resolved when all the async work is complete. If you don't do that, Cloud Functions assumes that all your work is complete, and will clamp down on all resources, and any pending work will be shut down.
The promise returned by translate.translate().then().catch() is being ignored. Your nested call to admin.firestore()...set() has a similar problem. It's not sufficient to just call then() and catch() on every promise because then() and catch() both return yet another promise.
You're also unnecessarily mixing usage of try/catch with catch() on the promise. You don't need both strategies for error handling, just one or the other.
When you used await in your second example, you forced JavaScript to pause until the async work represented by the promise returned by set() was complete. This allowed your function to return only after all the work was finished, which is why it worked correctly.
You might be helped by watching my video series on use of promises and async/await in Cloud Functions. Proper handling of promises is crucial to creating a correctly working function.

Resources