How to run installation script only once in react-native - react-native

I have created a react native app.
For this app one simple database installation script should run for only one time.
It should happen when the app is installed.
Is there any better way to add a condition or any function that will run this installation code only once while installation.

Usually, databases have a special feature that called migrations. It`s helpful when you trying migrate your database schemas from one version to another. But also, you can use it like pre-fill script for your database on initial step.
Also, you can have a special script, that can pre-fill your database on initial step. But in this case, you should properly change implementation depend on each new your database scheme.
For achieve 2, you can have some variable in your database (or key-value storage like AsyncStorage) like pre-filled that indicate state of your database. When you start application check if this value is false and start database pre-filling, otherwise just use your already prepared data.

You should use useEffect to execute a piece of your code once.
Import it like this;
import React, { useEffect } from 'react'
Then u can use it to execute once or when a fuction is called;
useEffect(
async () => {
const allItems = await fetchSomeData()
setStatus({ loading: false, dataList: allItems})
},
[
//when leave this array empty this above script will execute once
],
)

Related

expo-sqlite using existing local database

I am using expo and react native to build a truth or dare app. I want to store hundreds of truth or dare questions to feed to the user. I figured SQLite would be most efficient for this (and allow offline usage). I created the db using the DB Browser (SQLite) tool and created a single table named "Prompts" with several rows.
Here's the code I use for opening and performing a transation:
import database from "../assets/db/TruthOrDareDB.db"
const db = SQLite.openDatabase(database);
console.log(db);
db.transaction((tx) => {
console.log("transaction test");
tx.executeSql(
`
SELECT *
FROM Prompts;`,
[],
(_, result) => console.log("executeSql"),
(transaction, error) => console.log(error)
);
});
The openDatabase call returns a webSQLDatabase obj. I recieve the "transaction" log to the console but I do not get the "executeSql" log or an error. I would expect to get at least one, why am I not?
And as far as design do you agree that SQLite is the best for my goal?

Can you run a custom script that affects SQLite storage in react-native

I am creating an app that will save data on the local phone memory with react-native-sqlite-storage.
I want to make a script that will create a database (if it does not exist), create the necessary tables, and then populate those tables with mock data (basically, a seed script). I plan on adding a script to my package.json to seed this data, something like
{
....
"scripts": {
....
"seed": "ts-node index.ts"
}
}
Where index.ts will contain the necessary seeding script, something like:
// import react-native-sqlite-storage
const seedDatabase = () => {
// Populate the data ...
}
seedDatabase();
But I am uncertain if this would work. Will it work? If not, is there a way to seed data?
You can use this package to create and populate your database https://www.npmjs.com/package/sqlite3
then just run this to copy it to your device
adb push your_db.db /storage/emulated/0/your_db.db
In your react native code just use that file https://github.com/andpor/react-native-sqlite-storage#importing-a-pre-populated-database

webpack creating 100's of js chunks crippling performance for a single page view with vue cli

We have a vuejs 2 project.
We needed some function of dayjs.
We abstracted the dayjs into a single utility file and following the guide ended up with this:
import { i18n } from '#/plugins/i18n';
import dayjs from 'dayjs';
import calendar from 'dayjs/plugin/calendar';
dayjs.extend(calendar);
export default async (date: Date, locale?: string): Promise<string> => {
import(`dayjs\locales\${locale}`)
const time:any = i18n.t('datetime.dict');
return dayjs(date).locale(userLocale).calendar(null, {
lastDay: `[${time.yesterday} ${time.at}] LT`,
sameDay: `[${time.today} ${time.at}] LT`,
nextDay: `[${time.tomorrow} ${time.at}] LT`,
lastWeek: `[${time.last}] dddd [${time.at}] LT`,
nextWeek: `dddd [${time.at}] LT`,
sameElse: 'LLLL'
});
};
The app works perfectly fine, but vuejs is outputting every single langauge file from dayjs as a chunk and also adding the prefetch script tag to the index.html.
Has anyone else hit this issue and is the above code snippet wrong or should there be a more precise import?
Here is a screenshot of only some of the dayjs chunks.. each is completely the same with different langauge strings in... but we didn't even import the locale setting options yet.
#MichalLevĂ˝ gave the direction to the answer to this issue.
Essentially, webpack cannot know which single file to import when you say:
import(`dayjs\locales\${locale}`)
So.. it just creates a js chunk for every single file it finds. Which is not overly bad on its own.
When you combine this behaviour with vue-cli's default prefetch behaviour, this is when things get bad... the result is that every single chunk that webpack creates ends up being a "pre-fetched" line in the HTML head in the outputted index HTML file.
So when there is 400 chunks from a dynamic import (in this case locales from dayjs) then there is a prefetch for all of them.
It depends on your setup but.. for us, the app is also a PWA so there is effectively no requirement for prefetching as the PWA will also download... in fact it doubles the downloads.
The answer for us was to be more specific on the prefetch:
https://cli.vuejs.org/guide/html-and-static-assets.html#prefetch
And also, as we only needed a few languages, import only what was needed but being specific and not passing a variable to map to a path

Recommended dynamic runtime configuration technique on nuxtjs (other than dotenv)

I have been trying to use publicRuntimeConfig / privateRuntimeConfig
On nuxt 2.4.1, I have defined my runtime config as follows on nuxt.config.js
publicRuntimeConfig: {
DATA_API_HOST_URL: process.env.VUE_APP_DATA_API_HOST_URL,
},
privateRuntimeConfig: {
AUTH_APP_CLIENT_SECRET: process.env.VUE_APP_AUTH_APP_CLIENT_SECRET,
},
and calling it as follows on my login.vue
asyncData( ctx ) {
console.log(ctx.$config.DATA_API_HOST_URL)
//some activity
}
The keys are showing up on $config inside asyncData. I debugged on chrome dev tools. But value is not read from process.env.VUE_APP_DATA_API_HOST_URL. The value is showing up as undefined. However, process.env.VUE_APP_DATA_API_HOST_URL is showing the value OK. The whole point is to move away from process.env.
this.$config.DATA_API_HOST_URL also does not access the values.
'${DATA_API_HOST_URL}' is shown in examples but I believe it is only for explicit param declarations at asyncData like asyncData( { $config : {DATA_API_HOST_URL}).
When I pass values as it is using DATA_API_HOST_URL: process.env.VUE_APP_DATA_API_HOST_URL || 'https://test.api.com', it seems to copy the value fine using ctx.$config.DATA_API_HOST_URL!
Looking to me like copying process.env to *RuntimeConfig has a problem!
What is the recommended way of importing and using runtime configurations?
As per documentation in the Nuxt blog post you marked, the feature your are trying to use is released in 2.13 (you´re using 2.4 if i not misunderstood). That could be the reason behind the behaviour you're seeing.
I'd recommend update your project dependencies or trying another approach.
I think you should use Docker to set dynamic runtime config like link below:
https://dev.to/frontendfoxes/dockerise-your-nuxt-ssr-app-like-a-boss-a-true-vue-vixens-story-4mm6

Accessing vuex modules data from within a plugin

I am moving some data from the vuex store into its own module. Most of it works great, but I'm running into an issue that I can't seem to fix.
I have a plugin that I add, and that plugin also needs access to the store.
So at the top of that plugin, we import the store:
import store from '../store/store';
great - further down that plugin, I'm accessing the data of the store in a method that I expose on the service:
hasPermission(permission) {
return (store.state.authorization.permissions.indexOf(permission) >= 0);
}
Please note authorization is now a seperate module, and is no longer part of the root state object.
now the funny thing is that the above will return an error telling me indexOf is not a function.
When I add the following, however:
hasPermission(permission) {
console.log('Validating permission ' + permission);
console.log(store.state);
return (store.state.authorization.permissions.indexOf(permission) >= 0);
}
I notice that (1) the output to console is what I expect it to be, and (2), I'm not getting the error, and my menu structure dynamically builds as expected...
so I'm a bit confused to say the least...
authorization.permissions is updated each time a user authenticates, logs out, or chooses another account to work on; in these cases we fetch updated permissions from the server and commit it to the store, so we can build our menu structure based on up-to-date permissions. Works pretty good, but I'm not sure I understand why this fails to be honest.
The plugin is created as follows in the install:
Vue.prototype.$security = new Vue(
...
methods: {
hasPermission: function(permission) {
...
}
}
...
);