Scroll to top of ScrollView
React NativeReact Native Problem Overview
Is there a way to scroll to the top of a ScrollView
in response to a button press?
I can force a re-render
of the whole page but that seems very inefficient.
React Native Solutions
Solution 1 - React Native
- First add a
ref
attribute to yourScrollView
component. Example:<ScrollView ref='_scrollView'>
- Then wherever you want to scroll to top do this Example:
onPress={() => { this.refs._scrollView.scrollTo(0); }}
Solution 2 - React Native
in functional components
import { useRef } from 'react';
const scrollRef = useRef();
const onPressTouch = () => {
scrollRef.current?.scrollTo({
y: 0,
animated: true,
});
}
<ScrollView ref={scrollRef}>
...your elements
</ScrollView>
<TouchableOpacity onPress={onPressTouch}></TouchableOpacity>
Solution 3 - React Native
You can run the "scrollTo" method of the ScrollView. Check out the source.
You can get reference the ScrollView component by setting ref property and using this.refs as described here: https://facebook.github.io/react/docs/more-about-refs.html
Solution 4 - React Native
A simple example:
<ListView
ref={ref => this.listView = ref}
onContentSizeChange={() => {
this.listView.scrollTo({y: 0})
}}
/>
Solution 5 - React Native
scrollTo(x, y)
is now deprecated. It's now best to pass an object to scrollTo
like this:
this.refs.scrollView.scrollTo({x: 0, y: 0, animated: true})
Solution 6 - React Native
A Hooks solution (in Typescript)
A bit complex but may be useful for anyone using function components instead of classes.
ImperativeScrollView.tsx:
import React, {
useRef,
useImperativeHandle,
forwardRef,
RefForwardingComponent,
PropsWithChildren,
} from "react";
import { ScrollView, ScrollViewProps } from "react-native";
export interface ImperativeScrollViewHandles {
scrollToStart(options?: { animated: boolean }): void;
scrollToEnd(options?: { animated: boolean }): void;
scrollTo(options: { x?: number; y?: number; animated?: boolean }): void;
}
const ImperativeScrollView: RefForwardingComponent<
ImperativeScrollViewHandles,
PropsWithChildren<ScrollViewProps>
> = (props, ref) => {
const scrollViewRef = useRef<ScrollView>(null);
useImperativeHandle(ref, () => ({
scrollToStart: options => {
if (scrollViewRef.current) {
scrollViewRef.current.scrollTo({
x: 0,
y: 0,
animated: options ? options.animated : true,
});
}
},
scrollToEnd: options => {
if (scrollViewRef.current) {
scrollViewRef.current.scrollToEnd(options);
}
},
scrollTo: options => {
if (scrollViewRef.current) {
scrollViewRef.current.scrollTo(options);
}
},
}));
return <ScrollView ref={scrollViewRef} {...props} />;
};
export default forwardRef(ImperativeScrollView);
Usage:
const MyComponent: React.FC<MyComponentProps> = props => {
const scrollViewRef = useRef<ImperativeScrollViewHandles>(null);
return (
<ImperativeScrollView ref={scrollViewRef}>
<Button
title={"Tap me!"}
onPress={() => {
if (scrollViewRef.current) {
scrollViewRef.current.scrollToStart();
}
}}
/>
</ImperativeScrollView>
);
};
Solution 7 - React Native
< ScrollView ref={(ref) => { this.scrollListReftop = ref; }}>< /ScrollView>
Write this to get scroll on top
this.scrollListReftop.scrollTo({x: 0, y: 0, animated: true})
Solution 8 - React Native
Just to the point . The question was for scrollView and this worked fine for me:
<ScrollView
ref='_scrollView'
onContentSizeChange={() => { this.refs._scrollView.scrollTo({x: 0, y: 0, animated: true}); }}
>
Solution 9 - React Native
Simple example->
constructor(props) {
super(props);
this.state = {
}
this.listView1 = null
this.listView2 = null
this.listViewY = 0.0
this.scrollInterval = null
}
async componentDidMount() {
this.autoScroll()
}
autoScroll() {
setTimeout(() => {
this.scrollInterval = setInterval(() => {
if (this.listView !== null) {
this.listView.scrollTo({ y: this.listViewY + 1 })
this.listViewY += 1
}
}, 50);
}, 1000);
}
_stopScoller = () => {
if (this.scrollInterval !== null) {
clearInterval(this.scrollInterval)
}
}
render() {
return(
<ScrollView style={styles.fullListScrollView} ref={ref => this.listView = ref} onScrollBeginDrag={this._stopScoller}>
</ScrollView>
)
}
Solution 10 - React Native
With a button to control the scrollveiw or listview to top is possible.
first, you could use onScroll
method put event in it to detect the event.nativeEvent.contentOffset.y
of the ListView or scrollView,you can set a state to control its show or hide according to the
y`.
Then, set a button on your page, use onPress
method and .scrollTo
method to make it.
Here is an implementation can be used as a reference : https://www.npmjs.com/package/react-native-scrolltotop
Hoping this helps
Solution 11 - React Native
<TouchableOpacity onPress={()=>this.scrollListReftop.scrollTo({x: 0, y: 200, animated: true})}>
<Text>scroll up</Text>
</TouchableOpacity>
<ScrollView
ref={(ref) => { this.scrollListReftop = ref; }}
>
Solution 12 - React Native
If you are using FlatList you can do this:
import { FlatList } from 'react-native';
import React, { useRef } from 'react';
function Test(){
const flatListRef = useRef(null);
const onPress = () => {
flatListRef?.current?.scrollToIndex({ index: 0 });
}
return (
<>
<TouchableOpacity onPress={onPress}>
<Text>Scroll to Top<Text/>
</TouchableOpacity>
<FlatList
ref={flatListRef}
...
/>
</>
);
}