How to insert initial data( master data) into SQLite in React Native? - sqlite

I challenge to insert master data into SQLite in React Native.
But The data was inserted into SQLite table every time when I start my application.

Modules allow access to the database and transactions for data to be placed in the database repository.
and You can use AsyncStorage
Example
import {AsyncStorage} from 'react-native';
import { openDatabase } from 'react-native-sqlite-storage';
let db = openDatabase({ name: 'openDatabase.db' });
...
register_user = async () => {
const { user_name } = this.state;
const { user_address } = this.state;
if (user_name) {
if (user_address) {
db.transaction(function(tx) {
tx.executeSql(
'INSERT INTO table_user (user_name, user_address) VALUES (?,?,?)',
[user_name, user_address],
(tx, results) => {
console.log('Results', results.rowsAffected);
if (results.rowsAffected > 0) {
await AsyncStorage.setItem('First',true);
Alert.alert(
'Success',
'You are Registered Successfully'
);
} else {
alert('Registration Failed');
}
}
);
});
} else {
alert('Please fill Address');
}
} else {
alert('Please fill Name');
}
};
async componentDidmount(){
const check = await AsyncStorage.getItem('First');
if(check !== true) {
this.register_user();
}
}

Related

I want lockscreen on react native application and check passwords before screen load

I stored the app passwords in local storage of app and I just want to check the passwords before the screen renders in App.js
var passwords = null;
function get_passwords() {
// fetch the user defined settings
var db = openDatabase({ name: 'trans_DB.db', createFromLocation: '~www/test_Db.db' });
//to read currency
db.transaction((tx) => {
tx.executeSql(
'SELECT * FROM password_table', [],
(tx, results) => {
var len = results.rows.length;
if (len > 0) {
passwords = results.rows.item(0).passwords
}
}
);
});
}
function App(){
get_passwords();
if(passwords == null){
return lockScreen(); //contains lockscreen
}
else{
return mainScreen(); //if user didn't set the security to app then render main screen
}
}
I tried this but issue is database returns the values late and screen loads first before getting values from databases
you can set the password in state after retrieving from database
import React, { useState, useEffect } from 'react';
function App(){
const [passwords, setPasswords] = useState("");
// set password
useEffect(() => {
get_passwords()
},[]);
const get_passwords = () => {
// fetch the user defined settings
var db = openDatabase({
name: "trans_DB.db",
createFromLocation: "~www/test_Db.db",
});
//to read currency
db.transaction(tx => {
tx.executeSql("SELECT * FROM password_table", [], (tx, results) => {
var len = results.rows.length;
if (len > 0) {
passwords = results.rows.item(0).passwords;
setPasswords(passwords)
}
});
});
};
if(passwords == ""){
return lockScreen(); //contains lockscreen
}
else{
return mainScreen(); //if user didn't set the security to app then render main screen
}
}

Query data from Dynamo DB using Global secondary index

I am setting a serverless application using AWS Amplify
My frontend app has the following code
import React, { Component } from 'react';
import './App.css';
import Layout from './Containers/Layout';
import { Amplify, API } from 'aws-amplify';
import aws_exports from './aws-exports';
Amplify.configure(aws_exports);
const apiName = 'top3DynamoDBAPI';
let path = '/listings/';
let partitionKey = 'Restaurant';
class App extends Component {
componentDidMount() {
API.get(apiName, path + partitionKey).then(response => {
console.log(response)
});
}
state = {
listings: {
}
}
render() {
return (
<div className="App">
<Layout />
</div>
);
}
}
export default App;
in my backend API the get method to retrieve items from the table is as follows
/********************************
* HTTP Get method for list objects *
********************************/
app.get(path + hashKeyPath, function(req, res) {
var condition = {}
condition[partitionKeyName] = {
ComparisonOperator: 'EQ'
}
if (userIdPresent && req.apiGateway) {
condition[partitionKeyName]['AttributeValueList'] = [req.apiGateway.event.requestContext.identity.cognitoIdentityId || UNAUTH ];
} else {
try {
condition[partitionKeyName]['AttributeValueList'] = [ convertUrlType(req.params[partitionKeyName], partitionKeyType) ];
} catch(err) {
res.statusCode = 500;
res.json({error: 'Wrong column type ' + err});
}
}
let queryParams = {
TableName: tableName,
KeyConditions: condition
}
dynamodb.query(queryParams, (err, data) => {
if (err) {
res.statusCode = 500;
res.json({error: 'Could not load items: ' + err});
} else {
res.json(data.Items);
}
});
});
In my Dynamo DB table, I have a primary partition which has categories and one of them is called 'Restaurant' . So in my App.js I set some variables and call the API to get the items in ComponentDidMount
const apiName = 'top3DynamoDBAPI';
let path = '/listings/';
let partitionKey = 'Restaurant';
componentDidMount() {
API.get(apiName, path + partitionKey).then(response => {
console.log(response)
});
this returns all the items from the table where the primary partition matches a value called 'Restaurant'
Now I have global Secondary Partition called 'Listing_Location'
which currently has two values -- Sydney and Brisbane.
The backend API uses DynamoDB's Document Client and has the following variable initialised
const userIdPresent = false; // TODO: update in case is required to use that definition
const partitionKeyName = "Listing_Category";
const partitionKeyType = "S";
const sortKeyName = "Listing_Id";
const sortKeyType = "S";
const hasSortKey = sortKeyName !== "";
const path = "/listings";
const UNAUTH = 'UNAUTH';
const hashKeyPath = '/:' + partitionKeyName;
const sortKeyPath = hasSortKey ? '/:' + sortKeyName : '';
I am stuck at trying to figure out how to pass the secondary partition to my backend so I can lookup items based on location. Please can you help with this.
I was able to solve it with a combination of info from
DynamoDb how to query a Global Secondary Index? and
https://medium.com/#ole.ersoy/sending-an-email-parameter-with-amplify-api-get-request-4c1c8dc0c952
Now, my App.js looks like
componentDidMount() {
let params = {
'queryStringParameters': {
location: 'Brisbane'
}
}
API.get(apiName, path, params).then(response => {
this.setState({
listings: response
})
console.log(response)
});
}
New get function is
/* NEW GET ATTEMPT*/
app.get(path, function (req, res) {
if (userIdPresent) {
req.body['userId'] = req.apiGateway.event.requestContext.identity.cognitoIdentityId || UNAUTH;
}
const location = req.query.location;
var queryItemParams = {
TableName: tableName,
IndexName: "ListingGSI",
KeyConditionExpression: "#location = :v_location",
ExpressionAttributeNames: {
"#location": "Listing_Location"
},
ExpressionAttributeValues: {
":v_location": location
}
};
dynamodb.query(queryItemParams, (err, data) => {
if (err) {
res.statusCode = 500;
res.json({ error: 'Could not load items: ' + err });
} else {
res.json(data.Items);
}
});
});

Sending data to an imported module in React Native

I have a module called Chat.js that imports Fire.js in order to send data (message comes into Chat.js, and Fire.js handles storage).
I have a recipient's user ID that is only currently available in Chat.js, but it is important to get to Fire.js in order to store appropriately.
I removed some info for brevity, this is my current Chat.js:
import Fire from './Fire';
class Chat extends React.Component<Props> {
state = {
messages: [],
};
get user() {
return {
name: this.props.navigation.state.params.name,
_id: Fire.shared.uid,
};
}
render() {
return (
<GiftedChat
messages={this.state.messages}
onSend={Fire.shared.send}
user={this.user}
/>
);
}
componentDidMount() {
Fire.shared.on(message =>
this.setState(previousState => ({
messages: GiftedChat.append(previousState.messages, message),
}))
);
}
componentWillUnmount() {
Fire.shared.off();
}
}
export default Chat;
And this is my current Fire.js:
import firebase from 'react-native-firebase';
class Fire {
constructor() {
}
get ref() {
var recipient = 'recipientId'
return firebase.database().ref('messages/' + this.uid + '/' + recipient);
}
parse = snapshot => {
const { timestamp: numberStamp, text, user } = snapshot.val();
const { key: _id } = snapshot;
const timestamp = new Date(numberStamp);
const message = {
_id,
timestamp,
text,
user,
};
return message;
};
on = callback =>
this.ref
.limitToLast(20)
.on('child_added', snapshot => callback(this.parse(snapshot)));
// send the message to the Backend
send = messages => {
for (let i = 0; i < messages.length; i++) {
const { text, user } = messages[i];
const message = {
text,
user,
timestamp: this.timestamp,
};
this.append(message);
}
};
append = message => this.ref.push(message);
// close the connection to the Backend
off() {
this.ref.off();
}
}
Fire.shared = new Fire();
export default Fire;
I currently need to get the recipient ID, which is available in chat.js under
this.props.navigation.state.params.uid
Into the Fire.js lines:
get ref()
{
var recipient = 'recipientId'
I can't seem to get this uid into get ref()
Use getter and setters in Fire.js.
In Fire.js
setRecipient (id){
this.recipientId = id;
}
get getRecipientId () {
return this.recipientId;
}
And then call Fire.setRecipient(yourId) in Chat.js.

Expected Argument Error for .doc() when called on Firestore Collection

I want to create a new user document in my Cloud Firestore database whenever a new user logs in. Each doc should have a unique id and I want a "uid" property for each user to match the unique auto-generated id for the doc. At first, I just always ran an update on the user, but I figured it could be helpful to separate my create and update logic. As you can see I haven't worked out how to query if a user exists, but I figured I should test the createUser function before continuing.
Anyway, while I was testing my createUser function I ran into a compilation error.
ERROR in src/app/services/auth.service.ts(64,22): error TS2554:
Expected 1 arguments, but got 0.
UPDATE:
When I try to run the function from localhost after compilation I get this error in the console.
Function CollectionReference.doc() requires its first argument to be
of type string, but it was: undefined
Here is my proposed solution:
import { Injectable } from '#angular/core';
import { User } from './../models/user.model';
import { PermissionsService } from './permissions.service';
import { auth } from 'firebase/app';
import { AngularFireAuth } from 'angularfire2/auth';
import {
AngularFirestore,
AngularFirestoreDocument,
AngularFirestoreCollection,
} from 'angularfire2/firestore';
import { Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
#Injectable({
providedIn: 'root',
})
export class AuthService {
usersCollection: AngularFirestoreCollection<User> = null;
user: Observable<User>;
constructor(
private afAuth: AngularFireAuth,
private db: AngularFirestore,
private permissionsService: PermissionsService,
) {
this.usersCollection = db.collection('users');
this.user = this.afAuth.authState.pipe(
switchMap((user) => {
if (user) {
return this.db
.doc<User>(`users/${user.uid}`)
.valueChanges();
} else {
return of(null);
}
}),
);
}
loginGoogle() {
const provider = new auth.GoogleAuthProvider();
return this.oAuthLogin(provider);
}
loginFacebook() {
const provider = new auth.FacebookAuthProvider();
return this.oAuthLogin(provider);
}
loginTwitter() {
const provider = new auth.TwitterAuthProvider();
return this.oAuthLogin(provider);
}
oAuthLogin(provider) {
return this.afAuth.auth.signInWithPopup(provider).then((credential) => {
//if(the user exists already)
//this.updateUserData(credential.user);
//else
this.createUser();
});
}
createUser() {
const newUserRef = this.usersCollection.doc<User>(); // Error here
let newUser: User;
this.user.subscribe((userData) => {
newUser = {
uid: newUserRef.id,
email: userData.email,
photoURL: userData.photoURL,
displayName: userData.displayName,
roles: {
member: true,
},
permissions: this.permissionsService.memberPermissions;
};
});
newUserRef
.set(newUser)
.then(() => {
console.log('created user');
})
.catch((err) => {
console.log('Error adding user: ' + err);
});
}
updateUserData(user) {
const userRef: AngularFirestoreDocument<any> = this.db.doc(
`users/${user.uid}`,
);
const userPermissions = this.addPermissions(userRef);
console.log(userPermissions); // This works
const data: User = {
uid: user.uid,
email: user.email,
photoURL: user.photoURL,
displayName: user.displayName,
roles: {
member: true,
}, // I need to make sure this keeps current user roles
permissions: userPermissions,
};
console.log(data); // This works
userRef
.set(data)
.then(() => {
console.log('Success: Data for userDoc overwritten');
})
.catch((err) => {
console.error('Error writing to userDoc: ' + err);
});
}
addPermissions(userRef) {
const tempPermissions = [];
userRef.valueChanges().subscribe((userdata) => {
if (userdata.roles.reader === true) {
tempPermissions.push(this.permissionsService.memberPermissions);
}
if (userdata.roles.author === true) {
tempPermissions.push(this.permissionsService.authorPermissions);
}
if (userdata.roles.admin === true) {
tempPermissions.push(this.permissionsService.adminPermissions);
}
});
return tempPermissions;
}
checkPermissions(permission: string) {
if (!this.user) {
return false;
} else {
this.user.subscribe((data) => {
for (const p of data.permissions) {
if (p === permission) {
return true;
}
}
return false;
});
}
}
logout() {
this.afAuth.auth.signOut();
this.user = null;
}
}
I checked the documentation on the .doc() function and it should work fine with 0 arguments. It should be returning an empty doc reference. However, it keeps throwing the error saying it expects 1 argument. Any idea why this isn't working?

SQLite in Ionic 3 getting data null after navigate to another page

Please help me. I've made Database Provider to connect with SQLite in ionic 3. When i want to get the data rows it's always getting null but when I check data length it has 1
This is my DatabaseProvider
import { Injectable } from '#angular/core';
import { Platform } from 'ionic-angular';
import { SQLite, SQLiteObject } from '#ionic-native/sqlite';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Storage } from '#ionic/storage';
#Injectable()
export class DatabaseProvider {
private db: SQLiteObject;
private databaseReady: BehaviorSubject<boolean>;
constructor(private storage: Storage, private sqlite: SQLite, private platform: Platform) {
this.databaseReady = new BehaviorSubject(false);
this.platform.ready().then(() => {
this.sqlite.create({
name: 'takia.db',
location: 'default'
}).then((database: SQLiteObject) => {
this.db = database;
this.storage.get('database_filled').then(val => {
if (val) {
this.databaseReady.next(true);
} else {
this.initDB();
}
});
}).catch(e => { console.log(e); });
});
}
initDB(){
this.db.executeSql('CREATE TABLE IF NOT EXISTS users(user_id INTEGER PRIMARY KEY, username TEXT, email TEXT, password TEXT)', {})
.then(res => {
this.db.executeSql('INSERT INTO users VALUES(NULL,?,?,?,?)',['admin','admin.#email.com','password'])
.then(res => {
this.databaseReady.next(true);
this.storage.set('database_filled', true);
}).catch(e => {
console.log(e);
});
}).catch(e => {
console.log(e)
});
this.db.executeSql('CREATE TABLE IF NOT EXISTS questions(user_id INTEGER PRIMARY KEY, username TEXT, email TEXT, password TEXT)', {})
.then(res => {
this.db.executeSql('INSERT INTO users VALUES(NULL,?,?,?,?)',['admin','admin.tazkiaiibs.sch.id','bismillah'])
.then(res => {
this.databaseReady.next(true);
this.storage.set('database_filled', true);
}).catch(e => {
console.log(e);
});
}).catch(e => {
console.log(e)
});
}
getUser(){
return this.db.executeSql('SELECT user_id, username, email, password, COUNT(*) total FROM users', [])
.then(res => {
let users = [];
if (res.rows.length > 0) {
for (var i = 0; i < res.rows.length; i++) {
let row = res.rows.item(i);
users.push(row);
}
}
return users;
}, err => {
console.log('Error: ', err);
return [];
});
}
getDatabaseState() {
return this.databaseReady.asObservable();
}
}
and this is my code in component
constructor(public navCtrl: NavController,
public navParams: NavParams,
private dbProvider: DatabaseProvider,
private toastCtrl: ToastController) {
this.loadData();
}
loadData(){
this.dbProvider.getUser().then(data=>{
if(data.length>0){
this.id = data[0].id;
this.old_password = data[0].password;
this.username = data[0].username;
this.email = data[0].email;
let toast = this.toastCtrl.create({
message: 'ID '+data[0].username,
duration: 3000
});
toast.present();
}else{
let toast = this.toastCtrl.create({
message: 'No data'+data.length,
duration: 3000
});
toast.present();
}
});
}
When i run loadData function the length is not 0 but the data is null.
The comment under the question seemed to help, so I form it as an answer to hopefully collect some reputation points.
The problem seems to be a misformed SQL-query. The count(*) part makes the query return at least one row. Therefore the other fields might be NULL, when queried before data is added to the database.
The function "getUser" is called before the promise callback is executed.

Resources