getDerivedStateFromProps when to clear data? - react-native

getDerivedStateFromProps is static for component. but today I debug the app, I find other components data nextProp.x in getDerivedStateFromProps method when we define it the same.
the other situation is when a component is re-created, the nextProp.x still remains the pre-data.
so when the react-native will remove the getDerivedStateFromProps data, why the data is mixed?

the props is get from parent,if it remians the old data. it can cause by parent. if you use redux,it may be caused by it. the reduce state is not clear.

Related

Where does VueJS store the cached component when using keep-alive

I am looking for information on where Vue stores the cached component data when a component is wrapped in the keep-alive component. I looked at the local storage, cache storage, and session storage but I don't see anything obvious. I suspect that the cache is stored in the DOM but I was hoping that someone might know for sure or offer some clarification.
The issue I am having is that I have some Vue components that I am wrapping as web components using https://github.com/vuejs/vue-web-component-wrapper. This library is responsible for adding the keep-alive to my vue components. These components are then used inside other front end frameworks. The keep alive doesn't work as expected in this scenario, if I navigate away from the component and return the component is not restored to it's previous state. What I am expecting to happen is that navigation away from the component and returning restores the component to it's previous state as described in https://v2.vuejs.org/v2/guide/components-dynamic-async.html
After some digging around - in the implementation of keep-alive (Here).
You can see that the cache is stored locally on the component level, meaning that if the <keep-alive> is removed from the DOM it will lose its stored cache.
In theory, if you need it another way you may extend the component - create a prop like cacheName that you pass down to it. Have on mounted check if there is anything in localStorage for that prop to supplement it. Then add a watcher (deep) to watch for changes to the cache and store it in LocalStorage with the key coming for cacheName.
Some rough code of how the component may look - Here. Keep in mind that it may not be possible to get the object from Vue this way so you may need to copy the whole thing then add the code on top of it.

getDerivedStateFromProps() vs componentDidUpdate()

I am using componentWillReceiveProps in many places in my application. Now, I have to replace them with either getDerivedStateFromProps() or componentDidUpdate(). First I thought of using getDerivedStateFromProps as it s alternative of componentWillReceiveProps as suggested react-native docs. But some people are highly recommending not to use this method, Instead suggesting to use componentDidUpdate. But for my requirement all new props must be set with the state before render. getDerivedStateFromProps is the best place to do so.
Hence, which one to use between getDerivedStateFromProps and componentDidUpdate?
From the React docs
https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops
getDerivedStateFromProps is invoked right before calling the render method, both on the initial mount and on subsequent updates. It should return an object to update the state, or null to update nothing.
Deriving state leads to verbose code and makes your components
difficult to think about.
Make sure you’re familiar with simpler alternatives:
If you need to perform a side effect (for example, data fetching or an animation) in response to a change in props, use componentDidUpdate lifecycle instead.
If you want to re-compute some data only when a prop changes, use a memoization helper instead.
If you want to “reset” some state when a prop changes, consider either making a component fully controlled or fully uncontrolled with a key instead.

Is there a way to enforce order of execution of props on a Native Component?

I came across a bug in a React Native app that makes use of a native view component, and tracked it down to the order of execution of the property settings methods (e.g. #ReactProp methods on Android).
I found that I had to put the prop method that needed setting first as the last prop in the component's JSX declaration, which is a little counter-intuitive.
Is there a way to enforce this order?
Although this doesn't specifically answer the question, one way around this, when specific props are dependent on each other like this, is to bundle them in an object, which on Android would be passed to the native method via a ReadableMap. That way all the dependent data is in one place and can be handled in the correct order.

Props not propagating to children

I'm working on adding swipe to remove functionality to an app we are developing. For reasons we are not using an external library to handle this, so I am writing it myself.
In my project I have a container where I keep state. I use setState to update the state, and am passing state down to this child component as a prop. In the component below, componentWillReceiveProps is called with the correct value updates when they happen, but the child component of this is not receiving updates to its props. If this doesn't make enough sense or you need to see more code let me know. I've only included the parts of code that I feel are relevant since this is a private project.
constructor(props) {
super(props);
this.renderWishlistRow = this.renderWishlistRow.bind(this);
}
renderWishlistRow(product) {
return (
<WishlistRow
item={product}
onItemPress={this.props.onItemPress}
onRemoveAction={this.props.onRemoveAction}
shouldCloseRemoveButton={this.props.shouldCloseRemoveButton}
onScrollAction={this.props.onScrollAction}
itemPressed={this.props.itemPressed}
onEndScroll={this.props.onEndScroll}
/>
);
}
Then, inside the render function:
return (
<KeyboardAwareListView
dataSource={this.props.dataSource}
renderRow={this.renderWishlistRow}
renderSeparator={renderCardDividerAsSeparator}
onScrollBeginDrag={this.props.onScrollAction}
scrollEventThrottle={16}
onScrollEndDrag={this.props.onEndScroll}
/>
);
Thanks in advance for any help.
EDIT:
I am setting state in the parent component with this code:
this.setState({
shouldCloseRemoveButton: true,
});
I didn't originally include it because componentWillReceiveProps is being called with the correct state changes from the parent component.
EDIT 2:
My App Hierarchy for this part of the app is as follows:
WishlistContainer: contains the setState calls and passes as a prop: shouldCloseRemoveButton={this.state.shouldCloseRemoveButton}
Wishlist: passes props to its child WishlistRow: shouldCloseRemoveButton={this.props.shouldCloseRemoveButton}
WishlistRow: Continues to pass the props down as above, but componentWillReceiveProps is not called here, props are not updating at this level.
I'm not going to mark this as answered, because I want a real answer and what I did to work around this is not good enough for me.
That being said, my workaround was to move the piece of state I was trying to propagate into react-redux. Setting the redux state to contain what I needed using mapDispatchToProps, and then connecting the components that actually needed the state down the line using mapStateToProps, allows the components to receive the notifications they need to do their thing.
Again, I am not choosing this as the answer - even though it is what I did to solve the problem - because something else fishy is going on somewhere and I would like to see if anyone knows why things didn't work as they were.
EDIT
I've run into this issue other times since this originally happened. There is a prop that exists on the Flatlist - This is not the original component I used in the question, but the original component is deprecated now and the Flatlist has the, about to be mentioned, prop for this scenario - called extraData. This particular prop is also watched to help the Flatlist determine if it should rerender itself.
Since the ListView has become deprecated, I feel that using a Flatlist and making sure you pass in an extraData prop - assuming you have a different prop that will change with your list data changes - is an acceptable answer to this problem.

What is the difference between updated hook and watchers in VueJS?

I'm discovering VueJS and I don't understand exactly the differences between updated and watchers.
Updated hook
It is a lifecycle hook. According to the official documentation, it is triggered whenever data changes. So whenever a prop or a data is updated (the value, not only the pointer), updated is called.
Watchers
In the documentation, watchers are compared to computed properties. But in which cases would it be best to use updated instead of watchers ?
It seems that in both cases, DOM is not updated when the callback is called (nextTick() is required if we want to manipulate the changes in the DOM). The only difference I see is that watchers are only triggered when one precise property (or data) is updated where updated is always called.
I can't figure out what are the pros of updating whenever a data changes (updating) if we can be more accurate (watchers).
Here are my thoughts.
Thanks :)
The lifecycle hooks around update respond to changes in the DOM. Watchers respond to changes in the data. DOM changes are generally in response to data changes, but they might not be data owned by the component in question. One example where updated could be used is noticing that slot content has updated.
I think a better analogous lifecycle hook to the watchers may be the beforeUpdate hook. The updated hook is called after the virtual DOM has re-rendered, whereas beforeUpdate is called before the virtual DOM has re-rendered. You can see a visual representation of this on the diagram you linked to.
in which cases would it be best to use updated instead of watchers ? (...) I can't figure out what are the pros of updating whenever a data changes (updated) if we can be more accurate (watch).
The documentation says that you should prefer a watcher or computed property instead of updated if it is possible to achieve your goal that way. My understanding is that the updated hook was included to allow users to watch for any changes to the virtual DOM (see below).
Here's the explanation from the Vue 2.0 release notes on watch vs. updated:
User watchers created via vm.$watch are now fired before the associated component re-renders. This gives the user a chance to further update other state before the component re-render, thus avoiding unnecessary updates. For example, you can watch a component prop and update the component's own data when the prop changes.
To do something with the DOM after component updates, just use the updated lifecycle hook.