How to export and import js script? - vue.js

Hello I have a code like this which works fine in main.js
Vue.prototype.$assetsResolution =
document.body.clientWidth * devicePixelRatio <= 1920 && document.body.clientHeight * devicePixelRatio <= 1080
? 1080
: 2160;
However, I have a lot of similar things and I would like to move the prototype code into another file.
For example, I tried to do it like this
//main.js
import "./vue-extensions/prototypes"
//prototypes.js
import Vue from "vue"
export {
Vue.prototype.$assetsResolution =
document.body.clientWidth * devicePixelRatio <= 1920 &&
document.body.clientHeight * devicePixelRatio <= 1080
? 1080
: 2160
}
But I have an error Unexpected token, expected "," in Vue.prototype

That syntax looks incorrect.
The external file does not need to export anything. It should just include the Vue.prototype.$assetsResolution assignment:
// prototypes.js
import Vue from 'vue'
Vue.prototype.$assetsResolution =
document.body.clientWidth * devicePixelRatio <= 1920 &&
document.body.clientHeight * devicePixelRatio <= 1080
? 1080
: 2160;
demo 1
You could also make this a Vue plugin by exporting a function that receives the Vue to modify:
// prototypes.js
export default Vue => {
Vue.prototype.$assetsResolution =
document.body.clientWidth * devicePixelRatio <= 1920 &&
document.body.clientHeight * devicePixelRatio <= 1080
? 1080
: 2160;
}
...which would be used like this:
// main.js
import Vue from 'vue'
import MyPlugin from './prototypes'
Vue.use(MyPlugin)
demo 2

Related

React Native Reanimated 2 animating the length of an SVG Path

I'm trying to animate an SVG path's length form 0 to it's full length in React Native Reanimated 2. Here is my sample path:
const AnimatedPath = Animated.createAnimatedComponent(Path);
const animatedProps = useAnimatedProps(() => {
const path =
`M${width * 0.182} ${height * 0.59} ` +
`L${width * 0.443} ${height * 0.59} ` +
`L${width * 0.443} ${height * 0.39} `;
return {
d: path,
};
});
return (
<Svg height="100%" width="100%">
<AnimatedPath animatedProps={animatedProps} fill="none" stroke="red" strokeWidth="5" />
</Svg>
);
I have tried adding some interpolation to the width of the path with no luck. I have also tried looking at the interpolatePath() implementation from Redash but it seems to take in two paths as the output range. Anything else I should look at?
You need to use useAnimatedStyle instead of useAnimatedProps, and calculate d value for your Path component (wrapped by Animated) using useDerivedValue, based on some progress shared value which you change from 0 to 1 using withTiming.

Lazy Load screens with React Native Router Flux

There are several screens in my React Native application.
I am using React Native 0.56 and React Native Router Flux.
Is there a way for a screen to load all of its imports when the screen is actually needed, and not when the app is launched and bundle is parsed?
Because of this the initial load time of the app is increasing.
I came across RAM format in the React Native Performance Section.
https://facebook.github.io/react-native/docs/next/performance.html#enable-the-ram-format
How can I reduce the number of modules in loadedModuleNames??
index.android.js
import { AppRegistry } from 'react-native';
import AppContainer from './src/';
const modules = require.getModules();
const moduleIds = Object.keys(modules);
const loadedModuleNames = moduleIds
.filter(moduleId => modules[moduleId].isInitialized)
.map(moduleId => modules[moduleId].verboseName);
const waitingModuleNames = moduleIds
.filter(moduleId => !modules[moduleId].isInitialized)
.map(moduleId => modules[moduleId].verboseName);
// make sure that the modules you expect to be waiting are actually waiting
console.log(
'loaded:',
loadedModuleNames.length,
'waiting:',
waitingModuleNames.length
);
// grab this text blob, and put it in a file named packager/modulePaths.js
console.log(`module.exports = ${JSON.stringify(loadedModuleNames.sort())};`);
AppRegistry.registerComponent('Roots', () => AppContainer);
navigation/index.js
/**
* App Navigation
*
*/
import React from 'react';
import { Actions, Scene, ActionConst, Stack } from 'react-native-router-flux';
// Consts and Libs
import { AppConfig } from '#constants/';
// Components
// Scenes
import Placeholder from '#components/general/placeholder/index';
import ExperiencesScenes from '#navigation/experiences';
import AuthScenes from '#navigation/auth';
import MediateScene from '#navigation/mediate';
import HomeScene from '#navigation/home';
import SearchScene from '#navigation/search';
import NoticesScene from '#navigation/notices';
// import ShortlistedMapScene from '#navigation/shortlisted_map';
import IntroScene from '#navigation/intro';
import AssistantScene from '#navigation/assistant';
import NotificationSettingsScene from '#navigation/notification_settings';
import HighlightScene from '#navigation/highlight';
import TransportScene from '#navigation/transport';
import HelpScene from '#navigation/help';
import FaqScene from '#navigation/faq';
import DynamicListScene from '#navigation/component_list';
import BrandCoverScene from '#navigation/brand_cover';
import ListingsScene from '#navigation/listings';
import ShorlistedScene from '#navigation/shortlisted_list';
import SettingsScene from '#navigation/settings';
import OnTheWayScene from '#navigation/on_the_way';
import ItinerariesScene from '#navigation/itineraries';
import TempScene from '#navigation/temp';
import TipsScene from '#navigation/tips';
import SimpleSwipe from '#navigation/simple_swipe';
import Cities from '#navigation/cities';
// import ReferralScene from '#navigation/referral';
/* Routes ==================================================================== */
export default Actions.create(
<Stack key={'root'}>
{MediateScene}
{IntroScene}
{HomeScene}
{AssistantScene}
{SearchScene}
{NoticesScene}
{ShorlistedScene}
{SettingsScene}
{ListingsScene}
{TipsScene}
{BrandCoverScene}
{AuthScenes}
{ExperiencesScenes}
{NotificationSettingsScene}
{HighlightScene}
{TransportScene}
{HelpScene}
{FaqScene}
{DynamicListScene}
{OnTheWayScene}
{ItinerariesScene}
{SimpleSwipe}
{Cities}
</Stack>
);
Navigation Code looks similar to this
import React from 'react';
import { Scene, ActionConst } from 'react-native-router-flux';
// Consts and Libs
import { AppConfig } from '#constants/';
import { AppStyles, AppSizes, AppColors } from '#theme/';
// Scenes
import BrandCoverScreen from '#screens/brand_cover/index';
const navbarPropsTabs = {
...AppConfig.navbarProps,
hideNavBar: true,
};
/* Routes ==================================================================== */
const scenes = (
<Scene
{...navbarPropsTabs}
key={"brand_cover"}
component={BrandCoverScreen} >
</Scene>
);
export default scenes;
That's a bit more complicated then it seems - and it's not related to react-native-router-flux only - it would require support from metro to split the JS bundler into smaller pieces and load it in the right way.
It seems that Expo might do something like that to assets, but for the JS code I only saw something close to it hacking the react-native code in this article:
Lazy Bundle Loading in React Native by Karan Thakkar
https://medium.com/react-native-training/lazy-bundle-loading-in-react-native-5f717b65482a
And here the GitHub repository with the code used in the article:
https://github.com/karanjthakkar/RNLazyBundleLoading
In case the article or the repository goes offline, here is the diff he also showed in the article (this is a diff between original react-native and his fork:
diff --git a/React/Base/RCTBridge+Private.h b/React/Base/RCTBridge+Private.h
index 1995801ffcaa..cf1609bc9614 100644
--- a/React/Base/RCTBridge+Private.h
+++ b/React/Base/RCTBridge+Private.h
## -90,6 +90,12 ## RCT_EXTERN void RCTVerifyAllModulesExported(NSArray *extraModules);
*/
- (void)start;
+/**
+ * Called on the child bridge to run the executor and start loading
+ * the partial bundle
+ */
+- (void)lazyStart;
+
/**
* Used by RCTModuleData to register the module for frame updates after it is
* lazily initialized.
diff --git a/React/Base/RCTBridge.h b/React/Base/RCTBridge.h
index 5222a15b5ca7..d0be4652f4f5 100644
--- a/React/Base/RCTBridge.h
+++ b/React/Base/RCTBridge.h
## -223,4 +223,9 ## RCT_EXTERN NSString *RCTBridgeModuleNameForClass(Class bridgeModuleClass);
*/
- (BOOL)isBatchActive;
+/**
+ * Load a custom bundle into an existing bridge instance
+ */
+- (void)loadCustomBundle:(NSString *)bundleName;
+
#end
diff --git a/React/Base/RCTBridge.m b/React/Base/RCTBridge.m
index cee9aa0463e1..c1b3ae107599 100644
--- a/React/Base/RCTBridge.m
+++ b/React/Base/RCTBridge.m
## -319,6 +319,13 ## - (void)setUp
RCT_PROFILE_END_EVENT(RCTProfileTagAlways, #"");
}
+-(void)loadCustomBundle:(NSString *)bundleName
+{
+ _bundleURL = [NSBundle.mainBundle URLForResource:bundleName withExtension:#"jsbundle"];
+
+ [self.batchedBridge lazyStart];
+}
+
- (BOOL)isLoading
{
return self.batchedBridge.loading;
diff --git a/React/CxxBridge/RCTCxxBridge.mm b/React/CxxBridge/RCTCxxBridge.mm
index 4b7aaf375e5b..32df68ac43ec 100644
--- a/React/CxxBridge/RCTCxxBridge.mm
+++ b/React/CxxBridge/RCTCxxBridge.mm
## -382,6 +382,29 ## - (void)start
RCT_PROFILE_END_EVENT(RCTProfileTagAlways, #"");
}
+- (void)lazyStart
+{
+ __weak RCTCxxBridge *weakSelf = self;
+
+ __block NSData *sourceCode;
+ [self loadSource:^(NSError *error, RCTSource *source) {
+ if (error) {
+ [weakSelf handleError:error];
+ }
+
+ sourceCode = source.data;
+ RCTCxxBridge *strongSelf = weakSelf;
+ if (sourceCode) {
+ [strongSelf executeSourceCode:sourceCode sync:NO];
+ }
+ } onProgress:^(RCTLoadingProgress *progressData) {
+#if RCT_DEV && __has_include("RCTDevLoadingView.h")
+ RCTDevLoadingView *loadingView = [weakSelf moduleForClass:[RCTDevLoadingView class]];
+ [loadingView updateProgress:progressData];
+#endif
+ }];
+}
+
- (void)loadSource:(RCTSourceLoadBlock)_onSourceLoad onProgress:(RCTSourceLoadProgressBlock)onProgress
{
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];

Export URL for code organisation

I'm fairly new to React native, and i would like to have all my endpoints URLs in the same place
So, i have in my environement.js:
module.exports = {
SERVER: 'http://url.com',
API_VERSION: '/api/v3',
FULL_URL: this.SERVER + this.API_VERSION,
PLAYERS: this.FULL_URL + '/players',
TEAMS: this.FULL_URL + '/teams',
};
And on the other side in getGame.js
GLOBAL = require('../environement');
function getGame() {
console.log(GLOBAL.PLAYERS)
}
When i run my app i got
undefined/players
What am i doing wrong?
Thanks
You can try something like this using ES6.
const SERVER = 'http://url.com';
const API_VERSION = '/api/v3';
export const FULL_URL = SERVER + API_VERSION;
export const PLAYERS = FULL_URL + '/players';
export const TEAMS = FULL_URL + '/teams';
And then
import { FULL_URL, PLAYERS, TEAMS } from 'path/to/the/file'
Please take a look to this solution: https://github.com/luggit/react-native-config .
Also it will be very helpful when you will be have a few different environments and build agent for app in teamcity for example.

react-native .toLocaleString() not working on android

Updated 2022: With hermes enabled you should be good now.
I'm using .toLocaleString() on react-native for my number output. All work on IOS but seems not working on Android. This is normal or? Do I need to use a function for the decimal?
rather than using a polyfill or an external dependency, change the JSC your android app builds with. For the newer versions of react-native add or override the following line in app/build.gradle
def jscFlavor = 'org.webkit:android-jsc-intl:+'
On newer versions of RN >0.62 you can change the JSC (JavaScriptCore) build variant to support/include ICU i18n library and necessary data allowing to use e.g. Date.toLocaleString and String.localeCompare
Replace this line in your android/app/build.gradle file
def jscFlavor = 'org.webkit:android-jsc:+'
with this line
def jscFlavor = 'org.webkit:android-jsc-intl:+'
Clean build and react-native run android
Note
This variant is about 6MiB larger per architecture than default.
So, expect your APK size to increase by about 4MB for each APK architecture build if using def enableSeparateBuildPerCPUArchitecture = true and a more bigger APK if separate build per architecture is disabled
You can use
number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
This is an issue with Javascript core used to run react native in Android and not with react native itself. To overcome this, you'll have to integrate latest javascript core into your android build or upgrade react native to 0.59.
The details are documented in JSC Android Buildscripts repo.
Now for people who would like to do the locale string formatting without needing to integrate the entire javascript core, Javascript has Internationalization API which lets you format numbers to language sensitive format. Documentation available at MDN
This API is not available in android and needs to be polyfilled using Intl
In your project root, install the Intl library
yarn add intl
And then in your project's index file (index.js) add the following code at the top of the file:
if(Platform.OS === 'android') { // only android needs polyfill
require('intl'); // import intl object
require('intl/locale-data/jsonp/en-IN'); // load the required locale details
}
After doing the above two steps, you can now get locale string anywhere in your project using
new Intl.NumberFormat('en-IN', { style: 'currency', currency: 'INR' }).format(10000000);
In case you need to format number for another locale code, all the locale code details are available under the intl/locale-data/jsonp/ directory. Simply require the ones you need in your index.js file.
The reason for this is very old version of JavaScriptCore used by react-native. iOS embeds own version which is why it is working fine there.
Issue still exists (some reading about where it's heading https://github.com/facebook/react-native/issues/19737)
And more info about this from Airbnb devs
https://medium.com/airbnb-engineering/react-native-at-airbnb-the-technology-dafd0b43838 (search for "JavaScriptCore inconsistencies")
(value) => {
if (typeof value === 'number') {
const [currency, cents] = (value / 100).toFixed(2).toString().split('.');
return `${currency.replace(/\B(?=(\d{3})+(?!\d))/g, '.')},${cents}`;
}
return '0,00';
}
it's more recent and lightweight, please check
First install:
yarn add #formatjs/intl-getcanonicallocales #formatjs/intl-locale #formatjs/intl-pluralrules #formatjs/intl-numberformat
Check if need polyfill
import {shouldPolyfill} from '#formatjs/intl-numberformat/should-polyfill'
if (shouldPolyfill()) {
require('#formatjs/intl-getcanonicallocales/polyfill');
require('#formatjs/intl-locale/polyfill');
require('#formatjs/intl-pluralrules/polyfill');
require('#formatjs/intl-numberformat/polyfill');
require('#formatjs/intl-numberformat/locale-data/en-US');
}
see source: https://formatjs.io/docs/polyfills/intl-numberformat/
A very easy and straight forward way is to use a polyfill:
First it needs to be installed:
npm i number-to-locale-string-polyfill
This has to be added in your code, best just outside the class/function where you want to use .toLocaleString().
require('number-to-locale-string-polyfill');
I solved this using a custom function
function numberToMoney(amount, simbol = '$', decimalCount = 2, decimal
= ".", thousands = ",") {
decimalCount = Math.abs(decimalCount)
decimalCount = isNaN(decimalCount) ? 2 : decimalCount
const negativeSign = amount < 0 ? "-" : ""
const i = parseInt(amount = Math.abs(Number(amount) ||
0).toFixed(decimalCount)).toString()
const j = (i.length > 3) ? i.length % 3 : 0
return simbol + negativeSign + (j ? i.substr(0, j) + thousands : '') +
i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousands) + (decimalCount ?
decimal + Math.abs(amount - i).toFixed(decimalCount).slice(2) : "")
};
No need to install extra packages
Displaying currency values in React Native A zero dependencies solution:
const parseCurr = (value) =>
Platform.OS === 'android'
? '$' + price.toFixed(2)
: price.toLocaleString('en-US', { style: 'currency', currency:'USD' });
parseCurr(25.75) // => $25.75
A real life example (money values are multiplied by 100 for better cents precision) and converting the value to Brazilian Reais (R$)
export const getBRPrice = (price: number) => {
const parsedPrice =
( price / 100 ).toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' });
return Platform.OS === 'android'
? `R$${ ( price / 100 ).toFixed(2) }`
: parsedPrice;
};
// getBRPrice(450) => R$4,50
Solution: 1
Go to your android/app/build.gradle
Replace this line def jscFlavor = 'org.webkit:android-jsc:+'
with this
def jscFlavor = 'org.webkit:android-jsc-intl:+'
Stop the metro and rebuild your app.
Solution: 2
Otherwise, you can use this package https://www.npmjs.com/package/luxon
import import {DateTime} from 'luxon';
const date = DateTime.fromISO(new Date().toISOString());
const formatted = date.toLocaleString(DateTime.DATETIME_MED);
console.log(formatted);
Merging some responses from this thread, you can use this code where it is possible to customize the formatted response
const defaultOptions = {
significantDigits: 2,
thousandsSeparator: ',',
decimalSeparator: '.',
symbol: '$'
}
const currencyFormatter = (value, options) => {
if (typeof value !== 'number') value = 0.0
options = { ...defaultOptions, ...options }
value = value.toFixed(options.significantDigits)
const [currency, decimal] = value.split('.')
return `${options.symbol} ${currency.replace(
/\B(?=(\d{3})+(?!\d))/g,
options.thousandsSeparator
)}${options.decimalSeparator}${decimal}`
}
function numberWithCommas(x) {
return x.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
}
This will remove commas after decimal point
If you need two digits after the decimal and always want to round down
you can use below code.
Math.floor(1233.31231231 * 100) / 100).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
To round differently check out this resource
If these solutions don't work for you... In my case, I was using React Native with the expo web simulator and wanted to format minutes with 2 characters ie. 00, 01, ... 10, 11, etc. My solution was to check if minutes contained one character, if so, prepend a "0".
... + (date.getMinutes().toString().length == 1 ? "0" : "") + date.getMinutes().toString()

images in Elm 0.17

I am trying a test example with a single image:
import Html exposing (Html)
import Graphics.Element
main = image 960 500 "starry-night.jpg"
I am trying this out with elm-reactor and this simple result doesn't compile:
I cannot find module 'Graphics.Element'.
Module 'Main' is trying to import it.
Potential problems could be:
* Misspelled the module name
* Need to add a source directory or new dependency to elm-package.json
I tried importing the necessary grahics package, evancz/elm-graphics
john#me:~/Documents/Elm$ cat elm-package.json
{
"version": "1.0.0",
"summary": "helpful summary of your project, less than 80 characters",
"repository": "https://github.com/user/project.git",
"license": "BSD3",
"source-directories": [
"."
],
"exposed-modules": [],
"dependencies": {
"elm-lang/core": "4.0.1 <= v < 5.0.0",
"elm-lang/html": "1.0.0 <= v < 2.0.0",
"elm-lang/svg": "1.0.0 <= v < 2.0.0",
"evancz/elm-graphics": "1.0.0 <= v < 2.0.0"
},
"elm-version": "0.17.0 <= v < 0.18.0"
}
I came up with:
import Html exposing (Html)
import Element exposing (image, toHtml)
main = toHtml ( image 960 500 "starry-night.jpg" )
The name of the module is Element, not Graphics.Element, so that's why the compiler cannot find it.
Moreover, the image function returns an Element, while the main function desires something of the Html type.
A running version of your program could be something like
import Element exposing (..)
main =
toHtml (image 960 500 "starry-night.jpg")