react-native-scroll-into-view

Scroll a ReactNative View ref into the visible portion of a ScrollView
.
Similar to DOMElement.scrollIntoView()
for web, with some extras.
yarn add react-native-scroll-into-view
// or
npm install react-native-scroll-into-view --save
There is no native code: this library is compatible with Expo managed workflow.

ThisWeekInReact.com: the best newsletter to stay up-to-date with the React ecosystem:

Why ?
On long scrollable forms, can ensure errors become visible to the user on submit:

Building some kind of "sections index":

But really you are free to build whatever you want with it
Features:
- Declarative component API
- Imperative hook API
- Configurable at many levels
- Different alignment modes
- Insets
- Typescript definitions
- Support for composition/refs/other ScrollView wrappers (
Animated.ScrollView
, react-native-keyboard-aware-scroll-view
, glamorous-native
...)
Note we don't plan to support anything else than ScrollView. Virtualized lists generally offer methods to scroll to a given index.
Minimal hooks example
import { View, Text, ScrollView } from 'react-native';
import {
wrapScrollView,
useScrollIntoView,
} from 'react-native-scroll-into-view';
const CustomScrollView = wrapScrollView(ScrollView);
function MyScreen() {
return (
<CustomScrollView>
<MyScreenContent />
</CustomScrollView>
);
}
function MyScreenContent() {
const scrollIntoView = useScrollIntoView();
const viewRef = useRef();
return (
<>
<Button onPress={() => scrollIntoView(viewRef.current)}>
Scroll a view ref into view
</Button>
// in android if the scroll is not working then add renderToHardwareTextureAndroid this to view
<View style={{ height: 100000 }}>
<Text>Some long ScrollView content</Text>
</View>
<View ref={viewRef}>
<Text>Will be scrolled into view on button press</Text>
</View>
</>
);
}
API
import {
ScrollIntoView,
wrapScrollView,
wrapScrollViewConfigured,
useScrollIntoView,
} from 'react-native-scroll-into-view';
const options = {
align: 'auto',
animated: true,
immediate: false,
insets: {
top: 0,
bottom: 0,
},
computeScrollY: (scrollViewLayout, viewLayout, scrollY, insets, align) => {},
measureElement: viewRef => {},
};
const CustomScrollView = wrapScrollView(ScrollView);
function MyScreen() {
return (
<CustomScrollView
// Can provide default options (overrideable)
scrollIntoViewOptions={scrollIntoViewOptions}
>
<ScreenContent />
</CustomScrollView>
);
}
function ScreenContent() {
const scrollIntoView = useScrollIntoView();
const viewRef = useRef();
return (
<>
<Button
onPress={() => {
scrollIntoView(viewRef.current, options);
}}
>
Scroll a view ref into view
</Button>
<View style={{ height: 100000 }}>
<Text>Some long ScrollView content</Text>
</View>
<View ref={viewRef}>
<Text>Will be scrolled into view on button press</Text>
</View>
</>
);
}
class ScreenContent extends React.Component {
render() {
return (
<>
<ScrollIntoView>
<Text>This will scroll into view on mount</Text>
</ScrollIntoView>
<ScrollIntoView align="center">
<Text>This will scroll into view on mount and will be centered</Text>
</ScrollIntoView>
<ScrollIntoView animated={false}>
<Text>This will scroll into view on mount without any animation</Text>
</ScrollIntoView>
<ScrollIntoView immediate={true}>
<Text>
This will not throttle scrollIntoView calls, as by default it does
not make much sense to scroll into view multiple elements at the
same time...
</Text>
</ScrollIntoView>
<ScrollIntoView enabled={false}>
<Text>This will scroll into view whenever enabled becomes true</Text>
</ScrollIntoView>
<ScrollIntoView scrollIntoViewKey="some string">
<Text>
This will scroll into view whenever scrollIntoViewKey changes
</Text>
</ScrollIntoView>
<ScrollIntoView
onMount={false}
onUpdate={true}
scrollIntoViewKey="some string"
>
<Text>
This will scroll into on update (if it becomes enabled, or key
changes)
</Text>
</ScrollIntoView>
<ScrollIntoView scrollIntoViewOptions={options}>
<Text>
This will scroll into view on mount with custom option props
</Text>
</ScrollIntoView>
<View>
<ScrollIntoView
enabled={false}
ref={ref => (this.scrollIntoViewRef = ref)}
>
<Text>This will scroll into view when the button is pressed</Text>
</ScrollIntoView>
<Button
title="Make above text scroll into view with custom options"
onPress={() =>
this.scrollIntoViewRef.scrollIntoView(scrollIntoViewOptions)
}
/>
</View>
</>
);
}
}
You can also configure the HOC:
const CustomScrollView = wrapScrollViewConfigured({
options: scrollIntoViewOptions,
refPropName: 'ref',
getScrollViewNode: ref => ref,
scrollEventThrottle: 16,
})(ScrollView);
All these hoc configurations can also be provided to the CustomScrollView
as props.
Demos:
You can run the example folder as an Expo app with yarn start
It is also published on Expo





Recipes
Using in forms:
The integration with form libraries like Formik and Redux-form is very simple (see Formik example)

- By default, the first error field of the form will reveal itself
enabled={!!error}
means we'll only scroll into view fields that have an errorscrollIntoViewKey={submitCount}
means we'll scroll into view fields which still have errors on every Formik submit attempt (submitCount
is provided by Formik)
Using with react-native-keyboard-aware-scroll-view
KeyboardAwareScrollView
does not forward refs by default so we need to obtain ref by using the innerRef
prop:
const ScrollIntoViewScrollView = wrapScrollViewConfigured({
refPropName: 'innerRef',
})(KeyboardAwareScrollView);
TODOs:
- Tests
- Universal/Web support
- Support horizontal ScrollView?
Contribute
If your changes are impactful, please open an issue first.
License
MIT
Some code is inspired from contribution of @sebasgarcep of an initial scrollIntoView support for react-native-keyboard-aware-scroll-view
Hire a freelance expert
Looking for a React/ReactNative freelance expert with more than 5 years production experience?
Contact me from my website or with Twitter.