- [ScrollView] Use onScroll without event throttling #2228
- Comments
- aleclarson commented Aug 5, 2015
- ide commented Aug 5, 2015
- aleclarson commented Aug 5, 2015
- ide commented Aug 5, 2015
- aleclarson commented Aug 5, 2015
- ide commented Aug 5, 2015
- jeanregisser commented Aug 5, 2015
- yamill commented Aug 5, 2015
- koistya / App.js
- This comment has been minimized.
- koistya commented Aug 4, 2015 •
- This comment has been minimized.
- Peege151 commented Sep 8, 2015
- This comment has been minimized.
- polkovnikov-ph commented Sep 14, 2015
- This comment has been minimized.
- neptunian commented Oct 20, 2015
- This comment has been minimized.
- arturd-softgrad commented Dec 27, 2015
- This comment has been minimized.
- barsukov commented Dec 27, 2015
- This comment has been minimized.
- FallenMax commented Jan 7, 2016
- This comment has been minimized.
- blackcater commented Sep 12, 2016
- This comment has been minimized.
- ffxsam commented Sep 22, 2016
- This comment has been minimized.
- andyfaizan commented Dec 12, 2016
- This comment has been minimized.
- j6k4m8 commented May 5, 2017
- This comment has been minimized.
- jylopez commented Sep 5, 2017
- This comment has been minimized.
- haianhnc commented Oct 2, 2017
- This comment has been minimized.
- LyzioOh commented Oct 29, 2017 •
- This comment has been minimized.
- LyzioOh commented Oct 29, 2017
- This comment has been minimized.
- mehmetnyarar commented Jan 29, 2018
- This comment has been minimized.
- hnoor commented Mar 14, 2018
- This comment has been minimized.
- Lynn0108 commented Jun 14, 2018
- This comment has been minimized.
- billyma128 commented Aug 8, 2018
- This comment has been minimized.
- a-m-dev commented Aug 20, 2018 •
- This comment has been minimized.
- vishma9 commented Sep 12, 2018
- This comment has been minimized.
- venoms commented Sep 17, 2018 •
- react custom scrollbar with react-window #110
- Comments
- Rahul-Sagore commented Dec 17, 2018
- bvaughn commented Dec 17, 2018
- Rahul-Sagore commented Dec 18, 2018
- lottamus commented Jan 4, 2019
- Rahul-Sagore commented Jan 5, 2019
- simjes commented Feb 9, 2019
- piecyk commented Mar 3, 2019
- bvaughn commented Mar 3, 2019
- elixirdada commented Mar 26, 2019
- bvaughn commented Mar 26, 2019
- elixirdada commented Mar 27, 2019
- piecyk commented Mar 27, 2019
- elixirdada commented Mar 27, 2019
- jancama2 commented May 2, 2019
- jancama2 commented May 2, 2019
- piecyk commented May 2, 2019
- ChristopherHButler commented Aug 20, 2019
- ranihorev commented Aug 20, 2019 •
- ChristopherHButler commented Aug 21, 2019
- ChristopherHButler commented Aug 21, 2019 •
- ranihorev commented Aug 21, 2019
- piecyk commented Aug 21, 2019
- piecyk commented Aug 21, 2019
- ranihorev commented Aug 21, 2019
- piecyk commented Aug 22, 2019
- ChristopherHButler commented Aug 22, 2019
- piecyk commented Aug 22, 2019 •
- ranihorev commented Aug 22, 2019
- ChristopherHButler commented Aug 22, 2019
- ChristopherHButler commented Aug 22, 2019 •
- piecyk commented Aug 22, 2019 •
[ScrollView] Use onScroll without event throttling #2228
Comments
aleclarson commented Aug 5, 2015
I want to use the onScroll handler to setState another component in relation to the ScrollView ‘s contentOffset changing its value.
But the throttling of onScroll causes noticeable jumps. Sometimes the component that has setState called on it will never even update until much later on.
Is there a better way to achieve what I want?
The text was updated successfully, but these errors were encountered:
ide commented Aug 5, 2015
Have you tried setting the throttling interval below 16?
aleclarson commented Aug 5, 2015
@ide Yeah, it’s at 15. The jittering persists no matter where I set it. I’m testing on an iPhone 5s.
ide commented Aug 5, 2015
The jittering is likely due to the setState calls being too slow. If you replace the setState call with a console.log call does the performance noticeably improve?
aleclarson commented Aug 5, 2015
I don’t think I can easily test the performance by replacing setState with console.log since the only jittering is from the component I’m calling setState on.
Can I synchronize the rendering of my component and my ScrollView ?
ide commented Aug 5, 2015
It’s hard to tell if performance improves when I take out the forced re-render of the component, no?
Well, yeah — my guess is that re-rendering is too slow.
Is there a way to batch my setState with the changing contentOffset, or is onScroll called after the ScrollView is «re-rendered»?
It’s easier for me to explain the entire flow of events. When a native scroll event occurs on the main thread, it schedules a JS onScroll event for the next tick of the JS render loop (assuming no throttling) which runs every 16ms.
At the next tick on the JS thread, React runs your JS onScroll handler and your code calls setState which schedules a re-render before the end of the JS tick. At the end of the tick, the React subtrees with state changes are re-rendered and a JSON description of changes to the native views is sent back down to native. This all happens synchronously on the JS thread — meanwhile the main thread is free to run UIKit code without being blocked by JS. But if your JS is too slow, that also means the main thread won’t receive new updates in the meantime.
The native code processes the JSON description of changes on the shadow thread where it computes layout. Then it schedules the layout information to be applied to the native views at the next tick of the main thread. If you have a lot of expensive changes to the native views, this can take more than 16ms and your app will drop frames.
So basically if you’ve already configured the JS scroll view to throttle at 16ms or lower, you’re already getting scroll events as often as possible. In fact you may want to increase the throttling so that you don’t overload the system with too much work (React Native suffers from thundering herds atm).
jeanregisser commented Aug 5, 2015
I noticed the same thing when I implemented a parallax effect.
In my case onScroll was updating an animated value linked to the height of another component.
The lag in this configuration is very slight, maybe a frame or 2 when you scroll down really quickly before the height has caught up.
Not sure there’s something that can be done for now.
Or we would need the ability to run some JS code on the main thread.
yamill commented Aug 5, 2015
I think what you’re looking for is something like this:
You can then animate your view using the state values & interpolate. I do this for a pull to refresh animation inside my renderHeader function:
Источник
koistya / App.js
| import React from ‘react’ ; |
| let lastScrollY = 0 ; |
| let ticking = false ; |
| class App extends React . Component < |
| componentDidMount ( ) < |
| window . addEventListener ( ‘scroll’ , this . handleScroll , true ) ; |
| > |
| componentWillUnmount ( ) < |
| window . removeEventListener ( ‘scroll’ , this . handleScroll ) ; |
| > |
| nav = React . createRef ( ) ; |
| handleScroll = ( ) => < |
| lastScrollY = window . scrollY ; |
| if ( ! ticking ) < |
| window . requestAnimationFrame ( ( ) => < |
| this . nav . current . style . top = ` $ < lastScrollY >px` ; |
| ticking = false ; |
| > ) ; |
| ticking = true ; |
| > |
| > ; |
| render ( ) < |
| return ( |
| div > |
| nav ref = < this . nav >> |
| / nav > |
| div > |
| ); |
| > |
| > |
| export default App ; |
This comment has been minimized.
Copy link Quote reply
koistya commented Aug 4, 2015 •
This comment has been minimized.
Copy link Quote reply
Peege151 commented Sep 8, 2015
this didn’t work for me. I tried console logging inside the handleScroll and it never fired.
This comment has been minimized.
Copy link Quote reply
polkovnikov-ph commented Sep 14, 2015
What’s wrong with builtin onScroll event?
This comment has been minimized.
Copy link Quote reply
neptunian commented Oct 20, 2015
Yes, how does one use React’s built in onScroll event?
This comment has been minimized.
Copy link Quote reply
arturd-softgrad commented Dec 27, 2015
this didn’t work for me.
This comment has been minimized.
Copy link Quote reply
barsukov commented Dec 27, 2015
This comment has been minimized.
Copy link Quote reply
FallenMax commented Jan 7, 2016
This comment has been minimized.
Copy link Quote reply
blackcater commented Sep 12, 2016
I used React@15.3.1
I tried console logging inside the handleScroll. it never fired. I’m at a loss
This comment has been minimized.
Copy link Quote reply
ffxsam commented Sep 22, 2016
This solution works well for me:
(the styles.pane div is a fixed size with overflowY: ‘auto’ , and its child (thumbs) is the content to be scrolled)
This comment has been minimized.
Copy link Quote reply
andyfaizan commented Dec 12, 2016
@ffxsam Your solution worked for me. Thanks!
This comment has been minimized.
Copy link Quote reply
j6k4m8 commented May 5, 2017
To those that are having difficulty getting handleScroll to fire:
Try adding this.handleScroll = this.handleScroll.bind(this); to your constructor for that Component. That should make sure that you can call this.handleScroll from the lifecycle functions.
This comment has been minimized.
Copy link Quote reply
jylopez commented Sep 5, 2017
This worked for me:
This comment has been minimized.
Copy link Quote reply
haianhnc commented Oct 2, 2017
This comment has been minimized.
Copy link Quote reply
LyzioOh commented Oct 29, 2017 •
@jylopez That a perfect Simple React Solution. +1 +1 +1 Thanks
This comment has been minimized.
Copy link Quote reply
LyzioOh commented Oct 29, 2017
Hi @j6k4m8 , this.handleScroll = this.handleScroll.bind(this); Work very well with the traditionnal method declaration Syntax
In case you’re interested by making you’re constructor more dry you could also use the ES6 fat arrow syntax.
Fat arrow automatically bind this to the method, allowing shorter constructor. Especially when you have a lot of methods.
This comment has been minimized.
Copy link Quote reply
mehmetnyarar commented Jan 29, 2018
@jylopez, worked for me too, thanks!
This comment has been minimized.
Copy link Quote reply
hnoor commented Mar 14, 2018
@jylopez worked perfectly for me. thank you so much!
This comment has been minimized.
Copy link Quote reply
Lynn0108 commented Jun 14, 2018
@ffxsam your solution works for me
thank you a lot
This comment has been minimized.
Copy link Quote reply
billyma128 commented Aug 8, 2018
This comment has been minimized.
Copy link Quote reply
a-m-dev commented Aug 20, 2018 •
this is my solution :
coverGradRef is a ref that is in my component’s constructor and i pass that to child component, it works pretty smooth so far
and one more thing
after this.coverGradRef.current.style you can add cssText and add what every property you want like pure css , if you don’t like that you can use something like this.coverGradRef.current.style.top = ’10px’ and instead of top you can put any valid css property
This comment has been minimized.
Copy link Quote reply
vishma9 commented Sep 12, 2018
componentDidMount() <
document.addEventListener(‘scroll’, this.handleScroll, true);
>
handleScroll = () => <
console.log(‘scrolling . ‘);
>
This comment has been minimized.
Copy link Quote reply
venoms commented Sep 17, 2018 •
Note however that input events and animation frames are fired at about the same rate and therefore the optimization below is often unnecessary.
Источник
react custom scrollbar with react-window #110
Comments
Rahul-Sagore commented Dec 17, 2018
I am using react-custom-scrollbar and would like to integrate it with FixedSizeList .
I have checked the solution on this issue on react-virtualized : bvaughn/react-virtualized#692 (comment)
But the code is throwing error: Uncaught TypeError: Cannot read property ‘handleScrollEvent’ of undefined on scroll, in this function:
I have added ref= < instance =>< this.List = instance; >> on fixedSixe
component.
The text was updated successfully, but these errors were encountered:
bvaughn commented Dec 17, 2018
This library and react-virtualized are completely different implementations. General techniques you see on react-virtualized issues may often provide useful hints as to how to approach something, but specific implementation details like this are not applicable. (In react-virtualized , List decorates a Grid component. In react-window they are separate components, for better performance and size.)
I don’t know if something like react-custom-scrollbar would work with react-window since I’ve never tried it. It’s not something I’m very interested in supporting to be honest, since I think custom scrollbars are generally a bad idea because of how they impact performance. So I’m going to close this issue.
But we can continue to chat on it if you have follow up questions 😄
Rahul-Sagore commented Dec 18, 2018
I’ll figure out something about this, I am interested in using react-window because it’s lightweight and solves my issue. Even I don’t like to use custom scrollbar, but it’s not in my hand, we need custom design for scrollbar.
I’ll use react-virtualized , in worst-case.
Thanks 🙂
lottamus commented Jan 4, 2019
@Rahul-Sagore did you end up getting custom scrollbars working with react-window ?
Rahul-Sagore commented Jan 5, 2019
No, did not get time for that. Need to check and figure out.
simjes commented Feb 9, 2019
Not sure if @bvaughn approves this, but it seems to work: https://codesandbox.io/s/00nw2w1jv
piecyk commented Mar 3, 2019
Better approach would be to pass Scrollbars as outerElementType
bvaughn commented Mar 3, 2019
I love how many advanced things are possible using outerElementType or innerElementType
elixirdada commented Mar 26, 2019
I am trying to detect the scroll position at the bottom of react-window.
Is it possible? Do you have any ideas for that? I’d like to have codesandbox example.
bvaughn commented Mar 26, 2019
You should be able to use the available ref props to ask the list for its scrollHeight @rufoot.
elixirdada commented Mar 27, 2019
I have tried to use scrollHeight in the props. But I think there isn’t scrollHeight property in that.
@bvaughn Do you have any idea about that?
piecyk commented Mar 27, 2019
elixirdada commented Mar 27, 2019
When you scroll down at the bottom of react-window, then you can see one alert.
jancama2 commented May 2, 2019
@piecyk I have tried your solution with outerElementType and it is super laggy, have you battletested it?:D
jancama2 commented May 2, 2019
I have tried it with react-scrollbars-custom . Its is less laggy but still laggy. Have someone had any issues with lags using custom scrollbars?
piecyk commented May 2, 2019
@jancama2 didn’t battletested it 😂 Can you share Code Sandbox when it gets laggy?
ChristopherHButler commented Aug 20, 2019
I am using your implementation but I get an error saying forwardedRef is not a function.
The problem in my app that I am trying to solve is that I have a large list of items and when I click on one, the app will redirect to another route so I need to keep track of the scroll position (probably in redux) and then set the scroll position after the route change.
ranihorev commented Aug 20, 2019 •
@piecyk have you tried combining it with the InfiniteLoader from react-window-infinite-loader .
I’m using react-scrollbars-custom and it seems to be breaking the infinite loader 🙁
Update: I don’t think that it’s related to the infinite scroll component. I can’t get it to work with the custom scrollbar.
I’d appreciate if someone can share the implementation for react-scrollbars-custom with me
ChristopherHButler commented Aug 21, 2019
@ranihorev do you need to use that package? The code pen @piecyk shared above uses react-custom-scrollbars and works well (except when creating a ref, which for some reason is null in my code)
ChristopherHButler commented Aug 21, 2019 •
Ok I need to ask again. @piecyk I am using your code sample from above (where you replied to @simjes ). instead of using a fixed sized list though, I am using the auto sizer to wrap a VariableSizeList and specify the outerElementType. Something like this:
rowHeights[index]> itemCount=
I implement the CustomScrollbars and CustomScrollbarsVirtualList the same as you have however the ref is always null. I have tried creating the ref in the component I am using the AutoSizer as well as in it’s parent but it’s always null. I would really appreciate some help understanding why. As I mentioned above, I need to keep track of the scroll position and be able to set it on a route change in my app so the list doesn’t jump back to the top.
ranihorev commented Aug 21, 2019
@ChristopherHButler I’m already using that package multiple times in my code, so I’d rather keep using the same package. I solution is pretty similar however it doesn’t fetch new data ptoperly
piecyk commented Aug 21, 2019
@ChristopherHButler really hard to say without any Code Sandbox example of the issue, can you share something?
Basic the idea here is to set the ref from react-custom-scrollbars so the react-window
AutoSizer or VariableSizeList will work with this approach, as in this example
https://codesandbox.io/s/react-window-custom-scrollbars-t4352
piecyk commented Aug 21, 2019
@ranihorev can you also share Code Sandbox example?
ranihorev commented Aug 21, 2019
I also tried other variations (e.g. setting the ref to be the scroller wrapper) but no success.
piecyk commented Aug 22, 2019
@ranihorev this approach would be the same regardless of custom scroll implementation. They need to set reference to the same element that is responsible for scroll and handle that scroll event.
react-scrollbars-custom provides nicer api using render props pattern so you can do something like https://codesandbox.io/s/bvaughnreact-window-react-scrollbars-custom-pjyxs
Didn’t do any profiling, hope this helps 👍
ChristopherHButler commented Aug 22, 2019
@piecyk I am working with your demo here: https://codesandbox.io/s/4zjwwq98j4. I want to use the onScrollStop to dispatch an action in redux so I can set the scroll position (an idea from this thread: malte-wessel/react-custom-scrollbars#146 but onScrollStart and onScrollStop do not seem to work in my code or in your demo. Do you know why this is? Is there any way to pass props from the List to the Scrollbars?
piecyk commented Aug 22, 2019 •
@ChristopherHButler I think your best option is to use context to pass the props, something like
— Edited
If you unmount the whole list when route changes you can dispatch the action then, Last scrollOffset can be stored on ref and updated on every scroll change using the onScroll: function from VariableSizeList then you don’t need to pass props to Scrollbars
ranihorev commented Aug 22, 2019
@piecyk that’s awesome, thanks!
btw, it seems that all you need is the onScroll function (that I missed) and there is no need to forward a ref at all.
https://codesandbox.io/s/bvaughnreact-window-react-scrollbars-custom-99dn1
ChristopherHButler commented Aug 22, 2019
@piecyk sorry I should have mentioned my implementation of the VariableSizeList is wrapped in an AutoSizer and the component which renders it is a class based component so I’m not sure I can use context. Maybe this is why I cannot get onScrollStop to work?
ChristopherHButler commented Aug 22, 2019 •
Quick update:
I added component state and set it onScroll.
const mapStateToProps = state => ( <
scrollPosition: selectors.getTreeScrollPosition(state),
>);
const mapDispatchToProps = dispatch => ( <
setTreeScrollPosition: position => dispatch(actions.setTreeScrollPosition(< position >)),
>);
export default connect(mapStateToProps, mapDispatchToProps)(BaseTree);
`
then on componentWillUnmout I dispatch the action to set the position in redux like this:
my only issue now is being able to set the scroll position when the component re-mounts. I tried accessing the scrollTop method on this.listRef like this:
this.listRef.current.scrollTop() but I get an error that it is not a function. I’m not sure which property (this.listRef or this.outerRef) I can use to set the scroll position or in which method. I was thinking I could set it in the BaseTree’s componentDidMount as follows:
componentDidMount() < const < scrollPosition >= this.props; if (this.listRef.current) < // console.log('initializing scroll position to : ', scrollPosition); this.listRef.current.scrollTop(scrollPosition); >>
Any help to get this working would be greatly appreciated!
edit: I’m very sorry but my code does not seem to be formatting correctly in this editor so I apologize for that 🙁
piecyk commented Aug 22, 2019 •
@ranihorev forward ref to react-window is need for functions like scrollTo, scrollToItem to work
@ChristopherHButler context should work as exactly for this they are build, from docs
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
But yeah as mention before if you unmount the whole component on route change there is no need to pass the props. Would not store scrollPosition on state as you don’t need it while scrolling is happening, less re-renders, store it on ref.
Regarding outerRef , it’s not need in your case. listRef.current.scrollTo is the correct method you want to use. Hmm your idea to call the method in componentDidMount is correct and should work,
looks like some timing problem while setting refs, maybe AutoSizer delays render of the List that makes the this.listRef.current to be undefined,
hacky option is to, break from react life cycle with setTimeout, and call the ref on next tick
Источник