Louis345
Louis345

Reputation: 740

React Native's Animated.ScrollView is not allowing me to programmatically scroll to a certain position

Prior to upgrading to the newest version of React-Native and Expo this code block was working. The version it was working on was "expo": "^32.0.0".

I was previously able to programmatically move a child of Animated.ScrollView and now I'm no longer able to do so. Here is my testing code block that I am testing.

import React, { Component } from 'react';
import {
  StyleSheet,
  Text,
  View,
  Animated,
  TouchableOpacity,
  SafeAreaView,
  ScrollView
} from 'react-native';

export default class App extends React.Component {
  constructor(props) {
    super(props);
  }
  handleMove = () => {
    this.scroller.getNode().scrollTo({
      x: 200,
      y: 0,
      animated: false
    });
  };
  render() {
    return (
      <SafeAreaView style={styles.container}>
        <Text>Open up App.js to start working on your app!</Text>
        <Animated.ScrollView
          horizontal
          ref={scroller => {
            this.scroller = scroller;
          }}
        >
          <View
            style={{
              height: 100,
              width: 100,
              backgroundColor: 'red',
              margin: 5
            }}
          />
        </Animated.ScrollView>
        <TouchableOpacity onPress={this.handleMove}>
          <Text>Move</Text>
        </TouchableOpacity>
      </SafeAreaView>
    );
  }
}

const styles = StyleSheet.create({
  container: {}
});

After upgrading the code block no longer works on the newest version. The current version I am testing on is:

"dependencies": {
    "expo": "^34.0.1",
    "react": "16.8.3",
    "react-dom": "^16.8.6",
    "react-native": "https://github.com/expo/react-native/archive/sdk-34.0.0.tar.gz",
    "react-native-web": "^0.11.4"
  },

What is the correct way of doing this?

I added a snack to help illustrate my problem. ' https://snack.expo.io/@louis345/brave-banana

Upvotes: 13

Views: 10305

Answers (4)

Monte Thakkar
Monte Thakkar

Reputation: 11

I was able to get this working by using a simple setTimeout of 1 second.

Here's what my code looks like now:

setTimeout(() => {
  this.scrollView.scrollTo({
    x: DEVICE_WIDTH * current_index,
    y: 0,
    animated: false
  });
}, 1)

Similar to what Micheal suggested above, it's likely that this is caused by a mounting issue due to the deprecated componentWillMount in React which wasn't properly updated in ScrollView.

Upvotes: 1

Louis345
Louis345

Reputation: 740

I was able to resolve my issue by adding a prop to the scrollView. scrollToOverflowEnabled={true}

Now everything works as it once was. I hope this helps someone in the future.

Upvotes: 11

Michael
Michael

Reputation: 1864

I had a similar problem after upgrading from 0.57 to 0.60.

It seems like something has changed with the timing for mounting stuff (between RN versions). I will go through my code again (in a couple of days), as I suspect that I'm using some of the soon-to-be deprecated lifecycle functions. The fact that they are now considered "unsafe" to use might be due to some timing issues (wild guess).

I got my code to work by simply putting the scrollTo in a 100ms timeout. This indicates that the scrollview is not quite mounted at the first try. I'm actually fine with the timeout for my use case, but I want to solve this anyway because I don't like hacky solutions.

Upvotes: 0

hong developer
hong developer

Reputation: 13926

You can try this

<Animated.ScrollView // <-- Use the Animated ScrollView wrapper
  scrollEventThrottle={1} // <-- Use 1 here to make sure no events are ever missed
  onScroll={Animated.event(
    [
      {
        nativeEvent: {
          contentOffset: {x: 200,y: 0},
        },
      },
    ],
    {useNativeDriver: true}, // <-- Add this
  )}>
  {content}
</Animated.ScrollView>

Upvotes: 0

Related Questions