Closed usrbowe closed 4 years ago
Hello,
I've examined #146 and closed it due to it not meeting the checks, and also having too many files changed.
I'm wondering if this feature is really necessary. Looking at the code example in block #146, don't you think that you should call the scroll views' scrollTo() method? that will trigger an onScroll event which in turn will update the tracker's state.
@ognen I admit the PR is not correct, I just used branch I forked. I might create a separate PR with cleaner code. But anyway I'm not even sure, if this is good approach for that. So it's more like open for discussion.
So the main problem is, when using react-native-reanimated
, skele
component should not assign onScroll event listener, but rather get value from outside. Right now if I combine skele
and react-native-reanimated
it will throw error as seen in this demo: https://snack.expo.io/@usrbowe2/skele-reanimated
If you remove the <Viewport.Trcker />
all works fine.
Hi @usrbowe! I took a look at your Snack demo. It is true that there is an issue. Thanks for pointing it out.
However, setting the value from outside does not make much sense in the context of a "viewport tracker". Thus, I would for now consider the obstacle that you have experienced as a limitation of the tracker.
A potentially clean solution to your problem is to do a custom extension of WithEvents and call notifyViewportListeners
each time you want to communicate a viewport change to the Viewport.Aware
components.
You can import WithEvents
in your app like so:
import { Mixins } from '@skele/components';
// use Mixins.WithEvents
@bevkoski could you maybe provide a little example? I have the same issue currently. I am using an react-native-reanimated ScrollView to make a Cube transition and I would like to know when load the next images.
Currently I just get
n is not a functin. (In nt(t)', 'n' is an instance of _)
<Viewport.Tracker>
<Animated.ScrollView
removeClippedSubviews={true}
ref={(scroller) => {this.scroller = scroller}}
style={StyleSheet.absoluteFillObject}
showsHorizontalScrollIndicator={false}
scrollEventThrottle={16}
pagingEnabled={true}
decelerationRate={'fast'}
contentContainerStyle={{width: width * stories.length}}
onScroll={event(
[
{
nativeEvent: {
contentOffset: { x },
},
},
],
{ useNativeDriver: true },
)}
horizontal
/>
</Viewport.Tracker>
@usrbowe and @Hirbod, here is a Snack that shows how it can be done. Please check the ViewportNotifier.js
file for the details.
Thank you very much! Looks great and easy to understand. Will give it a try tomorrow!
@bevkoski I've spent nearly 2 hours, but my Images won't change - they will be "stuck" on the placeholder.
It took my a while to figure out, that react-native-reanimated does not have "listener", but I found a way around and I log my methods, they get called (and btw, every single pixel of movement calls a setState, JS FPS drops to 4 after 20px of swiping)
The way to use it with reanimated is like this btw:
onScroll={event(
[
{
nativeEvent: {
contentOffset: {
x: x => block([
set(this.state.x, x),
call([x], this.setEventDataForNotifier)
])
},
},
},
],
{
useNativeDriver: true,
},
)}
and inside the function setEventDataForNotifier I set
this.setState({
viewportOffsetX: x[0],
shouldMeasureLayout: false
})
But nothing happens. My cube gets transitioned but only with placeholders.
P.S: my scrollview is horizontal, not vertical. I set the contentContainer to screenWidth * items
P.S. some side information: The images take 100% of width and height, so I display 1 image on the full screen and when I scroll horizontically, I snap to the next image... but from my point of view it should work, while it doesn't
@Hirbod, the Snack shows that it is possible to use Skele Components together with React Native's Animated
. As it seems according to your findings, react-native-reanimated
does not work exactly the same, so that might be one source of issues.
It is true that setting the state as it is done in the Snack is not optimal in terms of performance. The approach is used for clarity's sake. For optimal performance, Mixins.WithEvents
should be extended in the class containing the ScrollView
(in the case of the Snack, App
). That way, unnecessary re-rendering will be avoided.
The images take 100% of width and height, so I display 1 image on the full screen and when I scroll horizontically, I snap to the next image...
The 100% size images could affect the whole situation. You can check whether setting the preTriggerRatio
parameter to 0.5
helps.
I'm afraid I cannot offer you much more assistance beyond this. Thanks and good luck!
Thanks for your help though. I played around few more hours and got it work, but the performance is draining so badly, that my efforts to optimize everything, were much more worse. I ended up dropping skele and kinda switch over to FlatList
If we want to use
Animated.ScrollView
and handle theonScroll
event in native thread, there is currently no way to pass theoffsetY/X
, out of the onScroll prop.In my example I used
react-native-reanimated
, so the entire event is driven in native thread. I can get offset values viacallback
and pass it back toViewportTracker
component viaref
.I created this PR, as a temporary workaround: #146