How to switch app’s UI and the Storybook UI - react-native

I am setting up Storybook to develop components in my app, what is the best way to switch between UI's?
Currently I am replacing my app entry with :
export default from './storybook';
How do I remove this when in production?

yarn add react-native-config, then pod install
If you're developing for Android, add an import line as described here
In your project root, create an .env file
Any environment variables you add to .env
can be accessed as Config.YOUR_ENVIRONMENT_VARIABLE
Now, add the environment variable LOAD_STORYBOOK=true to .env.
In App.tsx, change your code like below so that Storybook is rendered conditionally.
import StorybookUI from './storybook'
import Config from 'react-native-config'
const App = () => {
return (
// Your actual app
)
}
export default Config.LOAD_STORYBOOK === 'true' ? StorybookUI : App

Related

Quasar SSR app, "window is not defined" from vue-router

I'm taking a fairly simple Vue app built with Quasar, and adding ssr.
I'm using the Quasar CLI, and added ssr with quasar mode add ssr. This created the src-ssr/ folder and files as expected.
When I launch it with quasar dev -m ssr, I get:
App • Opening default browser at http://localhost:9100/
/Users/stevex/src/myapp/node_modules/vue-router/dist/vue-router.cjs:478
const { history, location } = window;
^
ReferenceError: window is not defined
at useHistoryStateNavigation (/Users/stevex/src/myapp/node_modules/vue-router/dist/vue-router.cjs:478:35)
at createWebHistory (/Users/stevex/src/myapp/node_modules/vue-router/dist/vue-router.cjs:570:31)
at Module.eval [as default] (/src/router/index.ts:14:14)
at __vite_ssr_exports__.default (/.quasar/app.js:91:44)
at async eval (/Users/stevex/src/myapp/.quasar/server-entry.js:86:9)
Node.js v18.7.0
Found the problem, it was the history mode.
I was using createWebHistory in routes/index.ts, but for SSR the history mode must be createMemoryHistory. With that change, the server-side-rendered page loads.
Details here:
https://router.vuejs.org/guide/essentials/history-mode.html#memory-mode
The default createHistory checks for the environment and picks a compatible one; I'd replaced that. Here's the default, which works:
const createHistory = process.env.SERVER
? createMemoryHistory
: process.env.VUE_ROUTER_MODE === 'history'
? createWebHistory
: createWebHashHistory;

Use global Vue 3 plugins in Storybook stories?

How can I use a Vue 3 plugin in Storybook stories?
For example, I use FormKit to create form elements in my components.
FormKit is rigged globally in my main.ts like so:
import { plugin, defaultConfig } from '#formkit/vue'
const app = createApp(App)
app.use(plugin, defaultConfig)
but this file isn't used by Storybook... so how can I do the same for Storybook?
I was able to find documentation here:
https://github.com/storybookjs/storybook/tree/47f753f5e8d084b4d544cf1ec76077a9382aa6b2/app/vue3
I learned that you are able to access the app created by Storybook in .storybook/preview.js by importing it from #storybook/vue3.
Example is copied from above link:
// .storybook/preview.js
import { app } from '#storybook/vue3';
app.use(MyPlugin);
app.component('my-component', MyComponent);
app.mixin({
/* My mixin */
});

Expo web build fails because of JSX in .js files

I have a Expo project to which I added victory-native library. When building for the web, Webpack complains about missing loader. The errors are of this pattern below and appear for all the files from this particular library
./node_modules/victory-native/src/components/victory-clip-container.js 10:22
Module parse failed: Unexpected token (10:22)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|
| export default class extends VictoryClipContainer {
> static defaultProps = Object.assign({}, VictoryClipContainer.defaultProps, {
| groupComponent: <G />,
| rectComponent: <Rect />,
How do I add the correct loader? Do I add something to the babel config? Or should I override the webpack configuration?
Babel is currently using only babel-preset-expo
As stated by Michael, native and web code can be differentiated using the naming in the files.
A simple complete solution is:
victory.js:
import * as Victory from 'victory';
export default Victory;
victory.native.js:
import * as Victory from 'victory-native';
export default Victory;
And when you want to use the victory:
import Victory from "./victory"; // this will default to victory.js or victory.native.js
// depending on the compilation target platform.
const VictoryBar = Victory.VictoryBar;
const VictoryChart = Victory.VictoryChart;
const VictoryTheme = Victory.VictoryTheme;
...
{
...
return <View style={styles.container}>
<VictoryChart width={350} theme={VictoryTheme.material}>
<VictoryBar data={data} x="quarter" y="earnings" />
</VictoryChart>
</View>
}
Whilst using victory-native in Expo apps that target iOS & Android is fully supported, we do not support building for the web with victory-native.
However, as both victory-native and victory share the same public API, it's possible to configure your Expo project to automatically use victory-native when building your native apps for iOS & Android, and victory when building your web app.
yarn add -D #expo/webpack-config
Then, create a webpack.config.js file at the root of your Expo project
const createExpoWebpackConfigAsync = require('#expo/webpack-config');
module.exports = async function(env, argv) {
const config = await createExpoWebpackConfigAsync(env, argv);
// resolve victory-native as victory for the Web app
config.resolve.alias['victory-native'] = 'victory';
return config;
};
Refered from the official documentation .
You cannot use victory-native imports for web and you cannot use victory import for react native.
I solved the issue by creating an file named victory.native.ts and victory.ts which containing all necessary imports.
victory.native.ts:
import * as Victory from 'victory-native'
victory.ts:
import * as Victory from 'victory'
Now you can import victory.ts in web and app.

Vue local config file per App installation

I am new the Vue.js and I am trying first steps with an app. So for understanding the basics, I want a local config file per App installation to customise some needed variables in the code.
So in my main.js I tried the following:
import Vue from 'vue'
import App from './App.vue'
let config;
try {
config = require('../config.json');
} catch (e) {
config = require('../public/config.json');
}
Vue.config.productionTip = false;
Vue.prototype.$localConfig = config;
new Vue({
render: h => h(App)
}).$mount('#app');
This is working, until I build the production version with the dist folder. If I open the config.json in the root of the dist and change a property value, I see always the first defined values from the development env. So is webpack making there some caching? Is this at all the right way of handling such a local config file per App installation?
Maybe someone could give me some tips on this.
Doing config = require('../config.json'); is the same as import config from "../config.json" in a way that it takes the content of your json file at build time, transform it into JS object and make's it part of your app bundle.
You can do what you propose in a comment (include the file in a script tag in your index.html) but that means your app is doing additional request to the server to load the config and by doing so increasing "time to render" (time user have to wait until the page is fully rendered)
Most common way to handle app configuration in Vue/Webpack world is by using Environment Variables - those also "work" at build time tho so you need to build your app separately for each environment
let config
const configPromise =
process.env.NODE_ENV === 'development'
? import('../config.json')
: import('../public/config.json')
configPromise.then(res => {
config = res.default
})

How to manage different config files for development and production with react-native

For testing my app locally I put dummy values in the code. Several times, I have forgotten to remove these values and pushed the changes, which is fine in development, but not in production. To avoid that this happens, I wanted to have a local config that overwrites the global config file. Something like :
const config = {
'auth.initial.email': '',
'auth.initial.password': '',
}
// Override defaults with local config
let extraConfig = null
try {
extraConfig = require('./config.local')
} catch(err) {}
Object.assign(config, extraConfig.default)
export default config
I believe this would work in node, but in react-native I get an error "Unable to resolve module". Is there a standard solution for this, or a simple way to catch and ignore import errors from JS in react-native?
You could use the __DEV__ variable from react-native.
This variable is set to true if you are in development mode.
It's set to false if your app is in production.