I haven't found any proper answer to this sadly.
I'm currently developing a react-native app with redux and I found out that the release version is getting slowed down by some development tools.
Here's an example:
const store = createStore(
Reducers,
composeWithDevTools(
applyMiddleware(thunk),
),
);
And this composeWithDevTools is obviously some development tool and in release I should use another function called compose.
What I'd like to do would be something like this:
//development
const store = createStore(
Reducers,
composeWithDevTools(
applyMiddleware(thunk),
),
);
//production
const store = createStore(
Reducers,
composeWithDevTools(
applyMiddleware(thunk),
),
);
//end
It would automatically choose the right code sample considering where I am. (Dev or release).
Do you guys know some tool I could use for this ?
Thanks in advance
You can use __DEV__ global constant. Moreover, babel compiler smart enough to completely remove code guarded by constants, so you also can reduce code size.
For example, we use this code to initialize store:
function setupStore(extra = {}) {
const middlewares = [thunk.withExtraArgument(extra)]
if (__DEV__) {
const createLogger = require('redux-logger').createLogger // redux-logger 3.x
const logger = createLogger()
middlewares.push(logger)
}
const store = createStore(reducer, applyMiddleware(...middlewares), autoRehydrate())
return store
}
Redux Logger has been changed a little while ago.
Now you need to import like this:
import { createLogger } from 'redux-logger';
In the example above you can do something like this:
const { createLogger } = require('redux-logger');
const logger = createLogger();
middlewares.push(logger);
Related
from nuxt 3 documentation,
https://nuxt.com/docs/getting-started/state-management
I'm told that I should never define ref outside script setup
since it will "be shared across all users visiting your website and can lead to memory leaks!"
I want to use vueuse's useBreakpoints,
https://vueuse.org/core/useBreakpoints/
I simply put them in composable and export,
and happily use them all across components.
but I see their type is globalThis.Ref
is it safe to use them as is,
or am I in big trouble as nuxt doc says?
// file: composables/useMedia.ts
import { breakpointsTailwind, useBreakpoints } from '#vueuse/core'
const breakpoints = useBreakpoints(breakpointsTailwind)
export const isDesktop = breakpoints.greaterOrEqual('lg')
export const isTablet = breakpoints.greaterOrEqual('sm') && breakpoints.smaller('lg')
export const isMobile = breakpoints.smaller('sm')
this is closely related to vue's response system
you don't need to worry about memory leaks when using compiler tools like nuxi
however here another problem is that react system cannot determine the dependencies and when to unmount. if you want to declare once and use globally use pinia otherwise use this code:
import { breakpointsTailwind, useBreakpoints } from '#vueuse/core'
export function useMedia() {
const breakpoints = useBreakpoints(breakpointsTailwind)
const isDesktop = breakpoints.greaterOrEqual('lg')
const isTablet = breakpoints.greaterOrEqual('sm') && breakpoints.smaller('lg')
const isMobile = breakpoints.smaller('sm')
return { isDesktop, isTable, isMobile }
}
and use
const { isDesktop } = useMedia()
note: your code doesn't react when changing the values. if you need response use computed
This is mainly a comprehension problem:
Considering the following expo docs, which aren't explaining what is going on under the hood,
import { useFonts } from 'expo-font';
import * as SplashScreen from 'expo-splash-screen';
SplashScreen.preventAutoHideAsync();
export default function App() {
const [fontsLoaded] = useFonts({
'Inter-Black': require('./assets/fonts/Inter-Black.otf'),
});
const onLayoutRootView = useCallback(async () => {
if (fontsLoaded) {
await SplashScreen.hideAsync();
}
}, [fontsLoaded]);
if (!fontsLoaded) {
return null;
}
return (
// Your app tree there.
);
}
What is going on here from my understanding is that you prevent the splashscreen from going away while you retrieve certain assets, like fonts.
When you do have your assets, you make the splashscreen go away and you launch your app by returning your components' tree.
The part I don't understand is why is it ok to return null if the fonts don't get loaded?
Since it is the initialization function, my mind want to think that if you return null to it, your app doesn't start and the user will be left wondering why...
Is there an explanation, a logic behind the hood actually refreshing something to recheck until it is ok and the assets are indeed loaded or something I don't know?
I know I have the case of my app not starting correctly every time right now and I'm wondering if this "return null" on the App.js function could be the culprit.
In our production applications with Vue 2.x, we have a toast component. This toast component is mounted once via a plugin (code below) and is then added to the Vue prototype making it accessible in every component instance.
This makes life a lot easier instead of having to add the toast to everywhere we use.
Vue 2.x plugin
export default {
install(vue: any, _: any) {
const root = new Vue({ render: (createElement) => createElement(Toast) });
root.$mount(document.body.appendChild(document.createElement("div")));
const toastInstance: Toast = root.$children[0] as Toast;
vue.prototype.$toast = {
show: (state: ToastState, text: string) => { toastInstance.show(state, text); },
hide: () => { toastInstance.hide(); }
};
}
Which can then be called in any component like:
this.$toast.show(ToastStates.SUCCESS, "Some success message");
I have recently started another project and would like to do something similar, except using Vue 3. Because we don't have access to this in the setup function, I can't use the same approach as before.
I have been looking into a few things, and have found a few ways of doing it, but none as a definitive best practice.
Provide / Inject:
This seems the most promising, where I can use
export const appInstance = createApp(App);
then
appInstance.provide("toast", toastComponentInstance)
which I can then inject in any components. The problem with this, is that to get it available in every component, it needs to be attached to the initial app instance, where it hasn't been created yet. Maybe I could manually mount it and pass it in (but that seems like a hack).
Composition:
I have also looked at this issue here: How to access root context from a composition function in Vue Composition API / Vue 3.0 + TypeScript? but didn't find that very useful and I had to do all types of hacks to actually gain access to the plugin. Gross code below..
export function useToast() {
const root = getCurrentInstance();
const openToast: (options: ToastOptions) => void = (options: ToastOptions) => {
root.ctz.$toast.open(options);
}
const closeToast: () => void = () => {
root.ctx.$toast.close();
}
return {
openToast,
closeToast
}
}
I have other ideas but they seem far fetched an hacky. Keen to hear peoples thoughts on other solutions. I just want a simple way to have 1 instance of a toast, that I can call two functions on to open / close it when and where I want.
This is roughly how I'd do it...
I'd use Composition API, because it makes passing around internals easy
(I'm using popup instead of toast for simplicity)
myPopup.vue
// internal
const popupMessage = Vue.ref('');
const popupVisible = Vue.ref(true);
// external
export const popUpShow = function(message) {
popupMessage.value = message
popupVisible.value = true
}
export const popupHide = function () {
popupVisible.value = false
}
export default {
setup(){
return {
popupMessage, popupVisible, popupHide
}
}
}
Some component, anywhere, composition or class based...
import { popUpShow } from "./myPopup";
export default {
methods: {
myTriggeredEvent() {
popUpShow("I am your Liter")
}
}
}
By exposing popUpShow, which acts as a singleton, you can import that from anywhere, and not have to worry about context.
There the drawback in using this kind of setup/architecture is that it doesn't scale well. The problem happens if your architecture reaches a certain size, and you have multiple triggers coming from various sources that the component needs to have complex logic to handle its state (not likely for this example though). In that case, a managed global store, ie. Vuex, might be a better choice.
I'm wondering how to go about using a mobx observable inside a useMemo hook. I know I could pass all possibly dependencies to the hook, but that could get kind of messy:
const MyComponent = observer(() => {
const people = useGetPeople();
const peopleFormatted = useMemo(() => {
return people.map(person => person.fullName);
},[ ...? ]);
});
I can't easily make every person's firstName be a dependency of useMemo. I'd think I could extract the functionality to a computed ... but I feel like this won't work:
const MyComponent = observer(() => {
const people = useGetPeople();
const peopleFormatted = computed(() => {
return people.map(person => person.fullName);
});
});
I feel like it will confuse mobx to create a computed inside a reaction that the reaction must depend on.
I know I could extract the computed to each person but I don't feel like that's a solution that matches every use case.
Thanks in advance!
Assuming const people = useGetPeople(); is an observable array of some sort of people objects...
const peopleFormatted = computed(() => {
return people.map(person => person.fullName);
}).get(); //note .get()
Should work fine inside the observer function body. See https://mobx.js.org/computeds-with-args.html#2-close-over-the-arguments
What is confusing me is useGetPeople();
That typically means you are using react's state api for managing state and reactions. ie: useState, etc.
Without seeing what useGetPeople() does under the hood, it's hard to give a concrete answer.
What is the best way to use Animated.Value () in react-native ?
With useState() or not ?
const [fadeAnim] = useState(new Animated.Value(0))
Or
const fadeAnim = new Animated.Value(0)
React-native doc: https://facebook.github.io/react-native/docs/animations
Thanks
I've been using this recently:
const [fadeAnim] = useState(() => new Animated.Value(0));
and for set value the standard:
fadeAnim.setValue(0);
Also, you might want to look at useRef too, since it is what documentation recommend:
const fadeAnim = useRef(new Animated.Value(0)).current;
/*
...
*/
fadeAnim.setValue(0);
Actually , Hook are a better way , so i'd say first choise
I came across a dodgy UI bug where settings hook values would render in the view instantly and mess up the animations. I fixed this by putting putting the animation value in a useState hook like so:
Before:
const foo = new Animated.Value(1)
After:
const [foo] = useState(new Animated.Value(1));
Use useRef() as recommended in https://reactnative.dev/docs/animated and https://reactnative.dev/docs/animations#animated-api.
const [fadeAnim] = useState(() => new Animated.Value(0)); is same but semantically "state" means getter and setter - without setter 'fadeAnim' will be same throughout the component's lifetime so no different than useRef(...).current