Flatlist scrollToOffset do not scroll at negative values instead it scroll to the top - reactjs

I am trying to implement a custom pull to refresh indicator using a Flatlist at some point i need the list to scroll at negative position to show the indicator at the top but scrollToOffset scrolls me to the top instead to y = 0
handleRelease() {
if (this.state.readyToRefresh) {
this.flatList.scrollToOffset({ offset: -130 });
}
}
<FlatList
ref={(flatList: any) => {
this.flatList = flatList;
}}
data={this.props.data}
renderItem={renderRowItem}
onScroll={this.handleScroll}
onResponderRelease={this.handleRelease}
scrollEventThrottle={16}
/>
Non-negative values seems working fine

It turns out you need to set scrollToOverflowEnabled to true to apply this behavior
ScrollView
When true, the scroll view can be programmatically scrolled beyond its
content size. The default value is false.

Related

react-custom-scrollbar-2 event on scroll top

I'm trying to implement on click scroll to top in react, but since I'm using custom scrollbar 2 I couldn't able to achieve it. The pageYoffset value is always 0 since I made the parent component max-height as 100vh and child component as scrollable. Here is what I got till now
<Scrollbars onScrollFrame={handleScroll}>
<ChildComponent/>
{
showButton && <button onClick={handleClick}><button/>
}
</Scrollbars>
In handleScroll
const {top} = values;
if(top > 0.02){
setShowButton(true);
}else{
setShowButton(false);
}
Depending on the top value I can show the button now I want to implement the scroll function when the button got clicked and scroll to the child component top
In handleClick I've tried to scroll it to top
window.scrollTo({ top: 0, behavior: "smooth" });
I've tried scrollIntoView with the top element as well it's not working.

the latest data to old data from top. i want scroll position last index of first of load. so from . i can scroll top to see new data. like whatsapp

when i scroll to top of last data iam doing api call , data appending , the latest data to old data from top. i want scroll position last index of first of load. so from . i can scroll top to see new data. like whatsapp`
const ifCloseToTop = ({ layoutMeasurement, contentOffset, contentSize }) => {
return contentOffset.y == 0;
};
<ScrollView
ref={ScrollViewRef}
// onLayout will make sure it scroll to Bottom initially
onLayout={() => ScrollViewRef.current.scrollToEnd()}
// We don't need `onContentSizeChanged`
// this onScroll fetches data when scroll reaches top
// then it scrolls to last position as you asked
onScroll={({ nativeEvent }) => {
if (ifCloseToTop(nativeEvent)) {
handleLoadMore()
ScrollViewRef.current.scrollTo({
y: nativeEvent.layoutMeasurement.height,
x: 0,
animated: false,
});
}
}}
scrollEventThrottle={400}>
<View style={styles.head}>
// messages
</View>
</ScrollView>
`

Office UI Fabric: ScrollablePane's Position is not being reset to the initial position when details list is updated

Replication Steps:
https://developer.microsoft.com/en-us/fluentui#/controls/web/scrollablepane
In the 'DetailsList Locked Header' scroll down to a non zero position exceeding the first page and enter 'sed' in the 'filter by name'. This updates the detailsList and the scrollbar does not go to the initial position.
Bug/Ask:
As we scroll down to let's say a position of 50 and now if there is an update to the details list with say suppose 350. The scrollbar is not returning to the starting position and it rerenders to a random position close to the top(in my case).
Approach/Temporary Hack:
Going through the code, I noticed that the initial scroll position of the scrollablepane is being refreshed only when the 'initialScrollPosition' props change in the implementation.
I tried changing the 'initialScrollPosition' prop in my component whenever the detailList updates by setting it to either 0 or 1.
Debugging this, the props for the initialScrollPosition did not change inside the ScrollablePane component did not change.
This did not work and the scrollable pane is still not set to the start.
Has anyone found a workaround or a solution for this?
I Had the same issue
I'm also using infinitive scroll(react-infinite-scroller) to load the data.
what I finally done , was replace scrollablepane by css.
(Function handleGetNext just loading new data, and variable dataToRender I keep on the state to make concatenation between old state and new)
<div>
{handleSelect()}
<div style={{ overflowY: "scroll", height: 500 }} id="containers">
<InfiniteScroll
pageStart={0}
loadMore={() => {
handleGetNext(overviewData.page);
handleSelect();
}}
hasMore={!loadingNext && !!overviewData && overviewData.page < overviewData.totalPages}
initialLoad={false}
useWindow={false}
>
<ShimmeredDetailsList items={dataToRender} enableShimmer={overviewLoading} .........../>
</InfiniteScroll>
</div>
</div>
And later what is tricky you need to set scroll position, depends where you want to scroll.
const handleSelect = () => {
const elemToScrollTo = document.getElementById("containers");
if (!!elemToScrollTo) {
elemToScrollTo.scrollTop = 2100;//example
}
};

How to check to see if a scrollbar is present in React?

I haven't seen a thread that handles this, at least not for React.
My case: I want to conditionally render a back to top button only when scrolling is an option. It makes no sense to have such a feature if it can't affect the page.
The only solutions I can find are in jQuery. I'm using react-scroll but couldn't find any functionality there for this.
When a scrollbar is visible then window.visualViewport.width < window.Width.
var buttonIsVisible = window.visualViewport.width < window.Width;
To check if scrollbar is visible in vertical appearance.
document.body.clientHeight > window.innerHeight
I added this code in a useEffect.
useEffect(() => {
if (document.body.clientHeight > window.innerHeight) {
something()
}
}, [state]);
Luke.
By "scrolling is an option" I am assuming here that you mean "when the scrollbar is visible."
As far as I am aware, there is not any way to check for scrollbar visibility using the React API. There is the DOM boolean window.scrollbars.visible; however, I have not had luck with this. It seems to always return true whether a scrollbar is visible or not. The following approach may work for you:
You could set an event listener for onScroll and check window.scrollY. If window.scrollY > 0, then you could conditionally render the button. If window.scrollY is 0, then the page is already scrolled to the top and there is no need to display the button.
Depending on the design of your web app, checking once for scrollbar visibility (e.g., on componentDidMount) may not be the best option, since some DOM elements may continue to load after the component initially mounts and the height of the page may change.
I hope this is helpful.
If you have a wrapper around the element that has the scroll you can detect the width difference.
<div className="wrapper">
<div className="scrollingContent">
Very long content here
</div>
</div>
const scrollBarWidth = this.wrapper.clientWidth - this.scrollingContent.clientWidth;
this.setState({ scrollBarWidth });
Most of the time (depending on edge cases where elements are sized differently). You can use an element ref to check if the scrollWidth is greater than the current width (or height for vertical scroll). The ref might not update scroll properties with useEffect hence why you need state in the dependencies array. Plus you will likely want to add a window resize event listener to run the same code.
const ref = useRef(null);
const [hasScrollBar, setHasScrollBar] = useState(false);
useEffect(() => {
function updateState() {
const el = ref.current;
el && setHasScrollBar(el.scrollWidth > el.getBoundingClientRect().width);
}
updateState();
window.addEventListener('resize', updateState);
return () => window.removeEventListener('resize', updateState);
}, [state]);
<div ref={ref} style={{ overflowX: 'auto' }}>
{state}
</div>

Scrolling to X,Y direction given number of pixels in react native scrollview

In react native there is a scrollTo function which programatically scrolls to a given x and y coordinate, animated or not.
https://facebook.github.io/react-native/docs/scrollview.html#scrollto
scrollTo({x: 0; y: 0; animated: true})
In some cases this is useful, but there are some cases in which I only want to scroll down for 100 pixels or scroll up for 200 pixels regardless of the position x,y on the screen. Is there a way to programatically do this in react-native currently.
You can keep track of your current X and Y scroll position in state by doing something like what is mentioned in this answer. So for example:
<ScrollView
ref={(scrollView) => { this._scrollView = scrollView; }}
onScroll={this.handleScroll}
/>
handleScroll = (event: Object) => {
this.setState({scrollX: event.nativeEvent.contentOffset.x, scrollY: event.nativeEvent.contentOffset.y})
}
Then you can move your scroll using scrollTo and the current position +/- whatever you wish. Example:
moveScroll = () => {
this._scrollView.scrollTo({y: this.state.scrollY + 100});
}
Do read through the linked StackOverflow answer though to understand the caveats of how onScroll works. I'm also not checking to see if you hit the end/beginning of the scroll window so check your bounds as well.

Resources