I'm reading the docs of mobx-react-lite and confusing with the difference between observer hoc and useObserver hook. According to the docs, observer hoc will trigger re-render twice while useObserver won't:
One good thing about this is that if any hook changes an observable for some reason then the component won't rerender twice unnecessarily. (example pending)
I'm not so familiar with mobx-react-lite, but interested in what causes that differences.
Here is the docs: https://mobx-react.js.org/observer-hook
The useObserver hook is only aware of observables referenced within a functional component, whereas the observer HOC is reactive to any observable props. The observer HOC actually just wraps the entire component in useObserver.
Related
In the official docs of react-navigation it says:
It's highly recommended to use the methods on the navigation object instead of using action creators and dispatch. It should only be used for advanced use cases.
But why is that? I didn't find any explanation for this strong recommendation in the react-navigation docs.
With CommonActions (or NavigationActions in react-navigation smaller equal 4.x) I can nicely create navigation functions which I can access from anywhere without the need of passing a navigation prop around. And I didn't encounter issues with it which I could relate to it being a CommonAction instead of a part of the navigation prop - even in more complex scenarios with many screens and special routing arrangements.
There are several reasons:
Methods on the navigation object are strictly type-checked, i.e. if you use something like TypeScript or Flow, you'll get errors if you pass incorrect values, it's way more relaxed with action objects, which will only log error during runtime.
When a method exists, it means the related navigator is definitely rendered. You can't call openDrawer if you don't have a drawer, but you can call dispatch(DrawerActions.openDrawer()).
It's more typing navigate('Home') vs dispatch(CommonActions.navigate('Home'))
without the need of passing a navigation prop around
Not sure how action creators help with that, but you could just use useNavigation
We are able to confirm that the render() method of our component is getting invoked. We also see that the data that needs to be shown is correctly passed in via props. However, the actual phone display won't repaint the updated UI until it is touched.
Interestingly this only happens in the production build not on the development builds of the app. Sigh.
We have seen this in the past when updates are done from InteractionManager.runAfterInteractions, but in this case we have removed every use of runAfterInteractions and are still seeing this behavior.
Using react native 0.57 but also seeing the same issue on 0.58.
I can provide more specifics if needed, but wanted to know if anyone has seen anything like this before and what if anything they did to fix such an issue.
I had this issue also when the content that should repaint was inside a 'ScrollView'. I refactored my code using a 'FlatList' instead of a 'ScrollView' and the problem disappeared.
It was a struggle, but I figured out what was happening.
TL;DR
The solution is to wrap your redux action dispatches inside a setTimeout(..., 0) whenever you are doing UI updates from a function passed to runAfterInteractions or from a Realm callback.
Some quick background:
I was dispatching a redux action inside a Realm callback. The action would in turn cause the UI to re-render, except the rendered UI would not repaint on screen until it was touched.
Similar behavior was observed when you dispatch redux actions from a callback passed to InteractionManager.runAfterInteractions. This makes sense because callbacks passed to runAfterInteractions wait for UI to do its thing and are then executed as a setImmediate batch. These callbacks were intended for heavy background jobs that would otherwise block UI rendering. So if one were to do UI rendering in such callbacks those would themselves get halted like a background job!
Solution:
The point of the realm callback is to notify you that some data has changed, so that you can re-render your UI. However, the realm callback was behaving like one passed to runAfterInteractions and so UI re-rendering was getting held up. I took a leap of faith and decided to move the Redux action dispatching code to a different queue, namely setTimeout. Here's what the fix looked like:
...
// assume this is in a callback passed to runAfterInteractions
// or in a realm callback
// PUT YOUR REDUX ACTION DISPATCHES IN A setTimeout
// callback
setTimeout(() => {
getFilteredCartAreas(dispatch, realm)
dispatch(new ActionCartAreaCardChanged())
}, 0)
...
The fix is to do the UI rendering logic inside a callback passed to setTimeout. Notice the zero delay; the goal is to simply move logic to a different queue that is not held up by UI interactions.
When you want to access params in a screen component passed through navigation (react native navigation), you have to do it like this for example:
this.myParameter = this.navigation.state.params.myParameter
Does this break demeter law ? And what if you want to use deep linking later on ?
A solution would be to just create a wrapper component that maps the navigation parameters as props.
Indeed, the Law of Demeter (or Principle of Least Knowledge) would require that your component know nothing about the internal structure of the navigation object.
In my view, the best thing would have been that the navigation object passed down to the component would have already had a function called params(), which would have returned a parameter map to you.
However, since this is not the case, you could just add it yourself - either by introducing a layer of indirection (through a function of your own that would look like screenParamsFrom(navigation), or you could try to hook into the navigation object and add the function yourself by supplying the navigation object to the root navigator:
<MyRootNavigator navigation={addNavigationHelpers({
dispatch: dispatch,
state: state,
params: paramsFunction})}/>
In this case, however, you'll have to manage the state yourself (through Redux or some other similar mechanism. See the integration guide).
I am working on a medium-sized app and notice a lot of memory increase when moving back and forth between components.
I put this on the component:
destroyed(){
console.log(this
}
I was surprised to find a lot - if not all - the 'data' still there plus computed properties. I thought this was supposed to be clean at that point. What all should be expected to be destroyed by that point? Is this a cause for concern and a potential source of memory leaks?
I develop some admin pannel in durandal and have some view which show actively mutating data.
How can i force this view to repeatedly update, say, once in T seconds?
just give me a link to some sample/doc page/methods.
thanks
Actually, if you will use observable variables (which are part of KnockoutJs, and part of Durandal) in your application - you will see changes immediately. KnockoutJs Observables Documentation
If you are already use observables but need to make some delay between updating observable and refreshing UI - you can use Rate-limiting observable notifications which are delaying update notification for observable variables.