You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ScrollView: scrolling direction when using inverted prop #995
The problem
When using FlatList with inverted prop, the mouse scrolling direction is also inverted. I'm not sure if this is an issue per se, but I think only the content of the list should be inverted and not the direction of the scroll. I worked on an implementation for the same feature for the RLV and I tried to handle this on the onWheel event reversing the scroll direction of the container. This only happens on desktops, mobiles scroll is different so it works fine there.
Sounds like a good idea meaning, I'll implement this at some point, or sounds like a good idea for a PR? 😄
Pretty much what I did is, in case inverted is true, I listen to the onWheel event and then reverse the scroll by scrolling to Y minus the delta Y (or X in case of horizontal scrolling). Not sure where this should be implemented here, ScrollResponder maybe?
I'm open to a PR if you feel like it. No worries if not. Off the top of my head, I'm not sure where the best place for this to go is but can help figure that out if you're going to try
On Jun 14, 2018, at 18:56, Nicolas Gallagher ***@***.***> wrote:
I'm open to a PR if you feel like it. No worries if not. Off the top of my head, I'm not sure where the best place for this to go is but can help figure that out if you're going to try
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or mute the thread.
So I saw that I can add the onWheel prop to the scrollProps in the VirtualizedList and I could set the this._scrollRef.getScrollableNode().scrollTop but I'm not sure that's the best way of doing it, eve if I can calculate the correct delta for the position.
I also tried a different approach but didn't work either. Instead of scaling the elements with -1, I used flexDirection to reverse the scrollview entirely but even though the items are reversed, they are still mounted in the same order, so you'll see how the items are pushed down while loading. So it's not a solution.
On Jul 11, 2018, at 11:03, Mark Glagola ***@***.***> wrote:
@tafelito did you ever find a solution?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
Here's a version of that same codesandbox example with some scrolljacking (this._scrollNode.scrollTop -= e.deltaY;) to invert the scroll direction and a trick (transform: translate3d(0,0,0) scaleY(-1)) to force hardware acceleration for better scroll performance: https://codesandbox.io/s/react-native-h32if
Tested on macOS Mojave FF/Safari/Chrome July 14 2019
Update Dec 14 2020: Hooks version. Still working for me on a new project, not perfect but it's good enough
// invert scrollingconstflatlistRef=useRef();useEffect(()=>{letscrollNode=flatlistRef.current&&flatlistRef.current.getScrollableNode();if(!scrollNode)return;constlistener=scrollNode.addEventListener("wheel",e=>{scrollNode.scrollTop-=e.deltaY;e.preventDefault();});flatlistRef.current.setNativeProps({style: {transform: "translate3d(0,0,0) scaleY(-1)"}});return()=>scrollNode.removeEventListener("wheel",listener);});// needs to run any time flatlist mounts
Reacted by tafelito, Andrey Pyankov, Dillon Hafer, Martin Frouin, ChengQing and Robin Meier
There's also arrow keys, page up/page down, home/end, and mousewheel drag to consider. I think I've come up with a proof of concept for simpler way to do this that doesn't require reimplementing each type of scrolling: https://jsfiddle.net/4t2uyfpz/1/
The idea is to keep two scrollable elements: a wrapper with a visible scrollbar for the user, and an inverted inner element with position: sticky that gets scrolled by the script. Scroll events -- mousewheel or keyboard -- move the wrapper's scrollbar and we scroll the inner content accordingly. If items get added or removed inside the inverted list we scroll and resize the wrapper to keep it in sync.
(Right now there's some weird behavior where if you scroll to the top and then remove N elements, Chrome -- and only Chrome -- keeps you stuck to the top until you either scroll manually or add N+1 elements back. I'm not sure exactly what's up with that but there's hopefully a workaround.)
Heads up @staltz and @necolas – we've been using a workaround for the inverted wheel event thing for a while now. I saw this commit is in the pipeline to fix this issue, and it's more or less the same as the workaround we've been using.
However, we did have someone report an edge case with this solution though – if the list is in focus then pressing ArrowDown scrolls you up and ArrowUp scrolls you down. Maybe worth fixing for accessibility reasons?
Activity
necolas commentedon Jun 14, 2018
Sounds like a good idea
tafelito commentedon Jun 14, 2018
Sounds like a good idea meaning, I'll implement this at some point, or sounds like a good idea for a PR? 😄
Pretty much what I did is, in case inverted is true, I listen to the onWheel event and then reverse the scroll by scrolling to Y minus the delta Y (or X in case of horizontal scrolling). Not sure where this should be implemented here, ScrollResponder maybe?
necolas commentedon Jun 14, 2018
I'm open to a PR if you feel like it. No worries if not. Off the top of my head, I'm not sure where the best place for this to go is but can help figure that out if you're going to try
tafelito commentedon Jun 15, 2018
necolas commentedon Jun 16, 2018
Cool. This setup guide will get you started https://github.com/necolas/react-native-web/blob/master/.github/CONTRIBUTING.md
tafelito commentedon Jun 19, 2018
So I saw that I can add the onWheel prop to the scrollProps in the VirtualizedList and I could set the
this._scrollRef.getScrollableNode().scrollTopbut I'm not sure that's the best way of doing it, eve if I can calculate the correct delta for the position.I also tried a different approach but didn't work either. Instead of scaling the elements with -1, I used flexDirection to reverse the scrollview entirely but even though the items are reversed, they are still mounted in the same order, so you'll see how the items are pushed down while loading. So it's not a solution.
[-]scrolling direction when using inverted prop[/-][+]ScrollView: scrolling direction when using inverted prop[/+]mglagola commentedon Jul 11, 2018
@tafelito did you ever find a solution?
tafelito commentedon Jul 11, 2018
tafelito commentedon Aug 7, 2018
@necolas are you using FlatList at Twitter Lite? Because I saw that the messages window uses an inverted scroll and the direction works fine there.
Also I noticed that the home page uses some sort of window scroller but on the chat screen you can only scroll on the list and not outside
necolas commentedon Aug 7, 2018
No. Twitter PWA uses a custom scroller that isn't integrated with React Native at all, i.e., no support for the responder system etc
danalloway commentedon Feb 5, 2019
did some work on this over in #1241
unadlib commentedon May 3, 2019
I've had the same issue, and I'm not sure it doesn't seem to have a fix plan?
raphaelrk commentedon Jul 14, 2019
Here's a version of that same codesandbox example with some scrolljacking (
this._scrollNode.scrollTop -= e.deltaY;) to invert the scroll direction and a trick (transform: translate3d(0,0,0) scaleY(-1)) to force hardware acceleration for better scroll performance: https://codesandbox.io/s/react-native-h32ifTested on macOS Mojave FF/Safari/Chrome July 14 2019
Update Dec 14 2020: Hooks version. Still working for me on a new project, not perfect but it's good enough
shaylew commentedon Aug 16, 2019
There's also arrow keys, page up/page down, home/end, and mousewheel drag to consider. I think I've come up with a proof of concept for simpler way to do this that doesn't require reimplementing each type of scrolling: https://jsfiddle.net/4t2uyfpz/1/
The idea is to keep two scrollable elements: a wrapper with a visible scrollbar for the user, and an inverted inner element with
position: stickythat gets scrolled by the script. Scroll events -- mousewheel or keyboard -- move the wrapper's scrollbar and we scroll the inner content accordingly. If items get added or removed inside the inverted list we scroll and resize the wrapper to keep it in sync.(Right now there's some weird behavior where if you scroll to the top and then remove N elements, Chrome -- and only Chrome -- keeps you stuck to the top until you either scroll manually or add N+1 elements back. I'm not sure exactly what's up with that but there's hopefully a workaround.)
davidfant commentedon May 7, 2020
vmaark commentedon May 18, 2020
One thing to note is that on Firefox the scroll direction works correctly.
For the workaround codesandbox, here is the function component version:
https://codesandbox.io/s/react-native-dsyse
divonelnc commentedon Nov 6, 2020
smithydll commentedon Feb 10, 2021
@raphaelrk I had to add flatlistRef.current to the useEffect dependency otherwise the content in the flatlist would fire the effect several times
roryabraham commentedon Apr 27, 2022
Heads up @staltz and @necolas – we've been using a workaround for the inverted wheel event thing for a while now. I saw this commit is in the pipeline to fix this issue, and it's more or less the same as the workaround we've been using.
However, we did have someone report an edge case with this solution though – if the list is in focus then pressing
ArrowDownscrolls you up andArrowUpscrolls you down. Maybe worth fixing for accessibility reasons?staltz commentedon Apr 27, 2022
@roryabraham We solved the keyboard problem like this: https://github.com/staltz/manyverse/blob/master/patches/react-native-web%2B0.17.6.patch (I think it's too ugly to make an upstream PR)
[fix] inverted VirtualizedList supports wheel events
[fix] inverted VirtualizedList supports wheel events