David
David

Reputation: 2821

scrollTo is undefined on animated ScrollView

When using Animated.createAnimatedComponent(ScrollView) to create an animated ScrollView it's not longer possible to use scrollTo.

    const AnimatedScrollView = Animated.createAnimatedComponent(ScrollView);

    <AnimatedScrollView ref={(ref) => this.list = ref}>
      <View style={{height: 1000}} />
    </AnimatedScrollView>

Calling this.list.scrollTo({x: 0, y: 0}) gives the following error:

_this.list.scrollTo is not a function

It works fine on a normal ScrollView. Is there any way to solve this?

Upvotes: 35

Views: 28885

Answers (5)

max23_
max23_

Reputation: 6689

Try this to get the ref of the component returns from Animated.createAnimatedComponent method:

ref={(ref) => this.list = ref._component}

Then, calling the below should work:

this.list.scrollTo({x: 0, y: 0})

Upvotes: 23

jhm
jhm

Reputation: 4539

@max23_ 's answer might work for now, but is not the correct way of doing it - as a rule of thumb, we should never access private variables directly as these are often subject to change. (edit: no disrespect :-) )

Due to this pull request, the new and future-proof way of getting the wrapped component's ref is to use the getNode() utility method, as accessing private variables (prepended with _) is not safe from future API changes.

So, the new way of doing it is

    ref={c => (this.myRef = c)}

and then when calling the method, doing

    this.myRef.getNode().scrollTo({
      y: 0,
      animated: true,
    });

:-)

Upvotes: 57

D W
D W

Reputation: 346

Building on the answer from @jhm - the new, recommended way to create a ref to a component since React 16.3 is to use React.createRef() as mentioned by @cyqui.

With a normal (note: non-animated) component, we'd simple create a ref to the ScrollView in the recommended way:

scrollView = React.createRef();

<ScrollView
  ref={this.scrollView}>

and use static methods as such:

this.scrollView.current.scrollTo({x: number, y: number, animated: true|false})

EDIT: As of RN 0.62 the below is no longer necessary

However, when working with an Animated component, we're moving into direct manipulation which requires us to get the native node of the component before calling any static methods. Therefore, you'd end up with the following:

scrollView = React.createRef();

<Animated.ScrollView
  ref={this.scrollView}>
this.scrollView.current.getNode().scrollTo({x: number, y: number, animated: true|false})

Upvotes: 12

cyqui
cyqui

Reputation: 97

If RN >= 0.59 (maybe earlier) and the following Ref setup:

const ScrollViewX = Animated.createAnimatedComponent(ScrollView);

  _scrollView = React.createRef();

<ScrollViewX
      ref={this._scrollView}>

You can manually scroll an Animated component this way :

this._scrollView.current._component.scrollTo({x: number, y: number, animated: true|false})

(ScrollToOffset is deprecated and probably removed in 0.6)

Upvotes: 0

Liem
Liem

Reputation: 770

Just adding another answer as both "getNode" and "_component" solution didn't work for me. I'm using react native 0.57. Manage to make it work using scrollToOffset

componentDidMount() {
  this.refs.listRef.scrollToOffset({ offset: 0,  animated: false })
}

render() {
  return (
    <FlatList ref="listRef" ... />
  }
};

Upvotes: 1

Related Questions