React-Native: save user preferences - javascript

Native developers,
I really searched a lot but couldn't find anything that fits my needs.
I am new to react native and have a question.
I wonder how I can save user preferences of my app.
For example, I am displaying a dismissible badge on my screen -> user dismisses it -> how do I save this decision so the badge won't appear on every start again?
I thought about writing a .json file where all preferences are defined and read it on every start.
Is this a common way to realize it or is there any other solution.
Thank you very much

Updated Answer at February 2022
React native, officially deprecated the usage of its built-in AsyncStorage. The latest solution is to install the community package of it.
# Install via NPM
npm install --save #react-native-async-storage/async-storage
# ...or install via YARN
yarn add #react-native-async-storage/async-storage
# ...or install via EXPO
expo install #react-native-async-storage/async-storage
And the implementation is like this
import AsyncStorage from '#react-native-async-storage/async-storage';
const storeKey = '#storage_Key'
const storeData = async (value) => {
try {
await AsyncStorage.setItem(storeKey, value)
} catch (e) {
// saving error
}
}
const getData = async () => {
try {
const value = await AsyncStorage.getItem(storeKey)
if(value !== null) {
// value previously stored
}
} catch(e) {
// error reading value
}
}
deprecated doc: https://reactnative.dev/docs/asyncstorage
async storage doc: https://react-native-async-storage.github.io/async-storage/docs/install/
Consider another options: https://reactnative.directory/?search=storage
Old Answer
There are so many options out there, but the most common you can use is the React Native built-in AsyncStorage.
Sample Code
import { AsyncStorage } from "react-native";
const storeKey = 'myPreference';
storeData = async () => {
try {
await AsyncStorage.setItem(storeKey, 'I like to save it.');
} catch (error) {
// Error saving data
}
}
retrieveData = async () => {
try {
const value = await AsyncStorage.getItem(storeKey);
if (value !== null) {
// We have data!!
console.log(value);
}
} catch (error) {
// Error retrieving data
}
}
read more at https://facebook.github.io/react-native/docs/asyncstorage.html
Or you could reconsider 3rd party library like:
https://github.com/kevinresol/react-native-default-preference
https://github.com/mCodex/react-native-sensitive-info

Related

Firestore (Web version 9 modular): getDocsFromCache seems not working

I'm new to Firebase and I found getDocsFromCache. I heard that firebase updated it's version to version 9, (modular) and i have to use more than just query.get({source: "cache"}). But getDocsFromCache didn't work for me. Every time i call getDocsFromCache, it does not throw any errors but snapshot.empty is always true so i can't access to my documents(collection).
If i have to cache manually, how? If not, what am i missing?
Thank you.
import {
​collection,
​getDocs,
​getDocsFromCache,
​query,
} from 'firebase/firestore';
import { db } from '../firebase-config';
export const getReviews = async () => {
​const q = query(collection(db, 'review'));
​try {
​const snapshot = await getDocsFromCache(q);
​console.log(snapshot.empty); // always true but not throwing any error
​snapshot.forEach((doc) => {
​/* ... */
​});
​} catch (e) {
// never reach here
​const snapshot = await getDocs(q);
/* ... */
​}
};
From the documentation on configuring offline persistence:
For the web, offline persistence is disabled by default. To enable persistence, call the enablePersistence method.
So make sure to enable the cache by calling this right after initializing Firebase and Firestore:
import { enableIndexedDbPersistence } from "firebase/firestore";
enableIndexedDbPersistence(db);

How can I copy pouchdb 0000003.log file to Ionic 5 and retrieve the data?

My scenario is to use pouch db data in ionic and I successfully added pouch db package to ionic and created a sample and it worked fine. Now I have a scenario I have the below file
000003.log in which I have all the data, but in ionic it is storing in the indexdb so how can I use this 000003.log data and copy it to indexeddb or is there any way copy the contents ?
Below is my app code
import { Injectable } from '#angular/core';
import PouchDB from 'pouchdb';
#Injectable({
providedIn: 'root'
})
export class DataService {
private database: any;
private myNotes: any;
constructor() {
this.database = new PouchDB('my-notes');
}
public addNote(theNote: string): Promise<string> {
const promise = this.database
.put({
_id: ('note:' + (new Date()).getTime()),
note: theNote
})
.then((result): string => (result.id));
return (promise);
}
getMyNotes() {
return new Promise(resolve => {
let _self = this;
this.database.allDocs({
include_docs: true,
attachments: true
}).then(function (result) {
// handle result
_self.myNotes = result.rows;
console.log("Results: " + JSON.stringify(_self.myNotes));
resolve(_self.myNotes);
}).catch(function (err) {
console.log(err);
});
});
}
How to export/import the existing database in ionic app? Do I have to store in file system or indexeddb?
By default PouchDb will use IndexDb, so its doing it correctly. If you want to change storage you need to setup a different adapter.
I don't see where you set up the options for the local adapter, so I think you are missing the local & adapter setup options to support it
Now use the correct adapter you want PouchDB here
I've created an Ionic 5/Angular repo that demonstrates how to take a local pouchdb as described in the OP and load it as a default canned database in the app.
https://github.com/ramblin-rose/canned-pouch-db
The hurdles were not huge, but I encountered some problems along the way, mainly some wrangling with respect to pouchdb's es modules and module default exports.
Specifically, the documentation for pouchdb-replication-stream is not helpful for incorporation for Ionic5/Angular. I assumed the import
import ReplicationStream from 'pouchdb-replication-stream';
Would just work, but unfortunately at runtime this dread error would popup
Type Error: Promise is not a constructor
Ouch! That's a show stopper. However I came across the pouchdb-replication-stream issue es modules
Which prompted the solution:
import ReplicationStream from 'pouchdb-replication-stream/dist/pouchdb.replication-stream.min.js';
Anyway the highlights of the repo are 'can-a-pouchdb.js' and 'data.service.ts'.
can-a-pouchdb.js
This script will create a local node pouchdb and then serialize that db to app/assets/db, which is later loaded by the ionic app.
The important bits of code:
// create some trivial docs
const docs = [];
const dt = new Date(2021, 6, 4, 12, 0, 0);
for (let i = 0; i < 10; i++, dt.setMinutes(dt.getMinutes() + i)) {
docs[i] = {
_id: "note:" + dt.getTime(),
note: `Note number ${i}`,
};
}
// always start clean - remove database dump file
fs.rmdirSync(dbPath, { recursive: true });
PouchDB.plugin(replicationStream.plugin);
PouchDB.adapter(
"writableStream",
replicationStream.adapters.writableStream
);
const db = new PouchDB(dbName);
console.log(JSON.stringify(docs));
await db.bulkDocs(docs);
//
// dump db to file.
//
fs.mkdirSync(dumpFileFolder, { recursive: true });
const ws = fs.createWriteStream(dumpFilePath);
await db.dump(ws);
To recreate the canned database run the following from the CL:
$ node can-a-pouchdb.js
data.service.ts
Here's how the app's pouchdb is hydrated from the canned database. Take note the db is using the memory adapter, because as a demo app not persisting the db is desirable.
public async init(): Promise<void> {
if (this.db === undefined) {
PouchDB.plugin(PouchdbAdapterMemory);
PouchDB.plugin(ReplicationStream.plugin);
this.db = new PouchDB(DataService.dbName, { adapter: 'memory' });
// if the db is empty, hydrate it with the canned db assets/db
const info = await this.db.info();
if (info.doc_count === 0) {
//load the asset into a string
const cannedDbText = await this.http
.get('/assets/db/mydb.dump.txt', {
responseType: 'text',
})
.toPromise();
// hydrate the db
return (this.db as any).load(
MemoryStream.createReadStream(cannedDbText)
);
}
}

How to commit and push with simple-git (NODEJS)?

I'm trying to do a simple Commit & Push to an existing repo using simple-git however I can't find
any example regarding this issue in the API in NPM (or Github) of simple-git.
I'm talking about this package : https://www.npmjs.com/package/simple-git
Consider the code :
const gitRepo = 'REPO-URL';
const tempFolder = '...';
// Simple Git
const simpleGit = require('simple-git')();
const options = ['--depth', '1'];
const callback = () => {
console.log('Done cloning!');
// Now change some code in the cloned code
// and commit && push
};
// Cloning ...
simpleGit.outputHandler((command, stdout, stderr) => {
stdout.pipe(process.stdout);
stderr.pipe(process.stderr)
stdout.on('data', (data) => {
// Print data
console.log(data.toString('utf8'));})
})
.clone(gitRepo, tempFolder, options, callback);
How can we commit and push using simple-git ?
Like #Lawrence Cherone said :
You can just use the basic commands as is.
This is how i used it in my project ( though i got a submodule in it where this example is changing its (git)working directory to content(submodule) first. After that i just commit with a message.
app.post("/gitCommit", async function(req, res) {
try {
await git.cwd({ path: 'content' }).commit(req.body.msg);
res.sendStatus(200)
} catch(err) {
console.log(err)
}
});
If you already have a working and initialised repo your in,
then you could just do the following:
await git.commit("your_message")
await git.push()
await git.push('origin', 'master')
You can leave out the 'await' part depending on your code running async.

GoogleSpreadsheet is not a constructor error

(node:13696) UnhandledPromiseRejectionWarning: TypeError: GoogleSpreadsheet is not a constructor
Currently getting this error when trying to define GoogleSpreadsheet. Not sure what the issue could be here.
async function accessSpreadsheet() {
const doc = new GoogleSpreadsheet('166SrAlBzhYXLxxIrHCQR333y_w3pcxeG7rV3bkjAp2U');
await promisify(doc.useServiceAccountAuth)(creds);
const info = await promisify(dox.getInfo)();
const sheet = info.worksheets[0];
const input = {
transcript: data,
ticket: message.channel.name
}
await promisify(sheet.addRow);
}
accessSpreadsheet();
Above is my code, not all of it, but everything to do with google spreadsheet.
If you are using version 3 you may need to import it like this:
const { GoogleSpreadsheet } = require('google-spreadsheet');
You either have to re-install your google-spreadsheet api to 2.0.6 just to make it work
npm install google-spreadsheet#2.0.6
or just follow the new version of implementation from the docs
https://www.npmjs.com/package/google-spreadsheet

ReferenceError: fetch is not defined

I have this error when I compile my code in node.js, how can I fix it?
RefernceError: fetch is not defined
This is the function I am doing, it is responsible for recovering information from a specific movie database.
function getMovieTitles(substr){
pageNumber=1;
let url = 'https://jsonmock.hackerrank.com/api/movies/search/?Title=' + substr + "&page=" + pageNumber;
fetch(url).then((resp) => resp.json()).then(function(data) {
let movies = data.data;
let totPages = data.total_pages;
let sortArray = [];
for(let i=0; i<movies.length;i++){
sortArray.push(data.data[i].Title);
}
for(let i=2; i<=totPages; i++){
let newPage = i;
let url1 = 'https://jsonmock.hackerrank.com/api/movies/search/?Title=' + substr + "&page=" + newPage;
fetch(url1).then(function(response) {
var contentType = response.headers.get("content-type");
if(contentType && contentType.indexOf("application/json") !== -1) {
return response.json().then(function(json) {
//console.log(json); //uncomment this console.log to see the JSON data.
for(let i=0; i<json.data.length;i++){
sortArray.push(json.data[i].Title);
}
if(i==totPages)console.log(sortArray.sort());
});
} else {
console.log("Oops, we haven't got JSON!");
}
});
}
})
.catch(function(error) {
console.log(error);
});
}
If you're using a version of Node prior to 18, the fetch API is not implemented out-of-the-box and you'll need to use an external module for that, like node-fetch.
Install it in your Node application like this
npm install node-fetch
then put the line below at the top of the files where you are using the fetch API:
import fetch from "node-fetch";
This is a quick dirty fix, please try to eliminate this usage in production code.
If fetch has to be accessible with a global scope
import fetch from 'node-fetch'
globalThis.fetch = fetch
You can use cross-fetch from #lquixada
Platform agnostic: browsers, node or react native
Install
npm install --save cross-fetch
Usage
With promises:
import fetch from 'cross-fetch';
// Or just: import 'cross-fetch/polyfill';
fetch('//api.github.com/users/lquixada')
.then(res => {
if (res.status >= 400) {
throw new Error("Bad response from server");
}
return res.json();
})
.then(user => {
console.log(user);
})
.catch(err => {
console.error(err);
});
With async/await:
import fetch from 'cross-fetch';
// Or just: import 'cross-fetch/polyfill';
(async () => {
try {
const res = await fetch('//api.github.com/users/lquixada');
if (res.status >= 400) {
throw new Error("Bad response from server");
}
const user = await res.json();
console.log(user);
} catch (err) {
console.error(err);
}
})();
If you want to avoid npm install and not running in browser, you can also use nodejs https module;
const https = require('https')
const url = "https://jsonmock.hackerrank.com/api/movies";
https.get(url, res => {
let data = '';
res.on('data', chunk => {
data += chunk;
});
res.on('end', () => {
data = JSON.parse(data);
console.log(data);
})
}).on('error', err => {
console.log(err.message);
})
fetch came to Node v17 under experimental flag --experimental-fetch
It will be available in Node v18 without the flag.
https://github.com/nodejs/node/pull/41749#issue-1118239565
You no longer need any additional package to be installed
EDITED - New Solution
To use the latest version (3.0.0) you must do the import like this:
const fetch = (url) => import('node-fetch').then(({default: fetch}) => fetch(url));
Old Anwser:
This may not be the best solution, but if you install this version :
npm install node-fetch#1.7.3
you can now use the line below without error's.
const fetch = require("node-fetch");
Node.js hasn't implemented the fetch() method, but you can use one of the external modules of this fantastic execution environment for JavaScript.
In one of the other answers, "node-fetch" is cited and that's a good choice.
In your project folder (the directory where you have the .js scripts) install that module with the command:
npm i node-fetch --save
Then use it as a constant in the script you want to execute with Node.js, something like this:
const fetch = require("node-fetch");
You should add this import in your file:
import * as fetch from 'node-fetch';
And then, run this code to add the node-fetch:
$ yarn add node-fetch
If you're working with typescript, then install node-fetch types:
$ yarn add #types/node-fetch
Best one is Axios library for fetching.
use npm i --save axios for installng and use it like fetch, just write axios instead of fetch and then get response in then().
You have to use the isomorphic-fetch module to your Node project because Node does not contain Fetch API yet. For fixing this problem run below command:
npm install --save isomorphic-fetch es6-promise
After installation use below code in your project:
import "isomorphic-fetch"
For those also using typescript on node-js and are getting a ReferenceError: fetch is not defined error
npm install these packages:
"amazon-cognito-identity-js": "3.0.11"
"node-fetch": "^2.3.0"
Then include:
import Global = NodeJS.Global;
export interface GlobalWithCognitoFix extends Global {
fetch: any
}
declare const global: GlobalWithCognitoFix;
global.fetch = require('node-fetch');
It seems fetch support URL scheme with "http" or "https" for CORS request.
Install node fetch library npm install node-fetch, read the file and parse to json.
const fs = require('fs')
const readJson = filename => {
return new Promise((resolve, reject) => {
if (filename.toLowerCase().endsWith(".json")) {
fs.readFile(filename, (err, data) => {
if (err) {
reject(err)
return
}
resolve(JSON.parse(data))
})
}
else {
reject(new Error("Invalid filetype, <*.json> required."))
return
}
})
}
// usage
const filename = "../data.json"
readJson(filename).then(data => console.log(data)).catch(err => console.log(err.message))
In node.js you can use : node-fetch package
npm i node-fetch
then :
import fetch from 'node-fetch';
here is a full sample in (nodejs) :
import fetch from "node-fetch";
const fetchData = async () => {
const res = await fetch("https://restcountries.eu/rest/v2/alpha/col"); // fetch() returns a promise, so we need to wait for it
const country = await res.json(); // res is now only an HTTP response, so we need to call res.json()
console.log(country); // Columbia's data will be logged to the dev console
};
fetchData();
In HackerRank, some libraries are installed by default and some are not.
Because it is running Node.js, the fetch API is not installed by default.
The best thing for you to do is to check whether the libraries are or not installed.
on the top of the exercise, there is the following:
const https = require('https');
Please try to add this to the top as well:
const axios = require('axios');
and then run the code.
If there is a compilation error, then it's not available, otherwise you can use axios, which is a good alternative to fetch
To use it with then, you can:
function getMovieTitles(substr){
axios.get(url)
.then(function(response){
console.log(response.data);
})
}
or taking advantage of the async/await
async function getMovieTitles(substr){
let response = await axios.get(url)
console.log(response.data);
}
This is the related github issue
This bug is related to the 2.0.0 version, you can solve it by simply upgrading to version 2.1.0.
You can run
npm i graphql-request#2.1.0-next.1
The following works for me in Node.js 12.x:
npm i node-fetch;
to initialize the Dropbox instance:
var Dropbox = require("dropbox").Dropbox;
var dbx = new Dropbox({
accessToken: <your access token>,
fetch: require("node-fetch")
});
to e.g. upload a content (an asynchronous method used in this case):
await dbx.filesUpload({
contents: <your content>,
path: <file path>
});
This worked for me:
const nodeFetch = require('node-fetch') as typeof fetch;
For me these are looking more simple.
npm install node-fetch
import fetch from "node-fetch";
There are actually a lot of different libraries for making fetch available in the browser.
The main ones I'm aware of are:
node-fetch
cross-fetch
whatwg-fetch
isomorphic-fetch
I currently use node-fetch, and it has worked fine, but I don't really know which one is "the best". (though the openbase.com pages I linked to provide some metadata on usage [eg. Github stars, npm downloads], which can help)
npm i node-fetch
Once installed, in your JavaScript file:
import fetch from "node-fetch";
Lastly make this change package.json file:
"type": "module"
Just make your app.js file Extension as app.mjs and the problem will be solved!!!:)
Solution without installations
Method 1
import { PLATFORM_ID } from '#angular/core';
import { isPlatformBrowser, isPlatformServer } from '#angular/common';
constructor(#Inject(PLATFORM_ID) private platformId: Object) {
// constructor code
}
ngOnInit() {
if (isPlatformBrowser(this.platformId)) {
// Client only code. Any javascript base functions
}
if (isPlatformServer(this.platformId)) {
// Server only code. Any javascript base functions
}
}
Method 2
import { PLATFORM_ID} from '#angular/core';
import { isPlatformBrowser } from '#angular/common';
#Component({
selector: 'app-navigation',
templateUrl: './navigation.component.html',
styleUrls: ['./navigation.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class NavigationComponent implements OnInit {
private isBrowser: boolean = false;
constructor(
#Inject(PLATFORM_ID) private platformId: Object
) {
this.isBrowser = isPlatformBrowser(platformId);
}
ngOnInit(): void {
if (this.isBrowser) {
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then((response) => response.json())
.then((json) => console.log(json));
}
}
}
DEMO - JSFIDDLE - Open console to view the fetch api service working
This answer does not directly answer this question. Instead it suggests for an alternative.
Why? Because the using 'node-fetch' is getting complicated since you cannot import the updated versions using const fetch = require('node-fetch') . You will have to do more things to just make it work.
Try using axios package:
Simple installation npm i axios
code for fetching goes like
const response = await axios.get(url).then(res => res.data)
Might sound silly but I simply called npm i node-fetch --save in the wrong project. Make sure you are in the correct directory.
If need install:
npm install --save global-fetch
then
var fetch = require("node-fetch");

Categories

Resources