23

I'm I understanding it correctly ? Does this two set of code meant the same thing ?Does it have any difference in performance or reliability ?

<ScrollView
 onScroll={Animated.event(
  [{nativeEvent: {contentOffset: {y: this.state.scrollY}}}]
)}
>
</ScrollView>

AND

handleScroll(e){
  this.setState({ scrollY : e.nativeEvent.contentOffset.y });
}

<ScrollView
 onScroll={(e) => this.handleScroll(e)}
>
</ScrollView>

Thanks

cjmling
  • 6,896
  • 10
  • 43
  • 79

4 Answers4

17

it's not the same. Animated.event is used to map gestures like scrolling, panning or other events directly to Animated values. so in your first example this.state.scrollY is an Animated.Value. you would probably have code somewhere that initialized it, maybe your constructor would looks something like this:

constructor(props) {
  super(props);
  this.state = {
    scrollY: new Animated.Value(0)
  };
}

in your second example this.state.scrollY is the y value (just the number) that was triggered in the scroll event, but completely unrelated to animation. so you couldn't use that value as you could use Animated.Value in animation.

it's explained here in the documentation

Zohar Levin
  • 2,364
  • 3
  • 19
  • 24
  • 7
    the fact that one is an Animated.Value and the other is not is exactly what makes the difference between the two pieces of code. what more would you expect? – Zohar Levin Apr 08 '18 at 10:15
16

If you want to handle the scroll you can use it this way:

handleScroll = (event) => {
    //custom actions
}

<ScrollView
 onScroll={Animated.event(
[{ nativeEvent: {
    contentOffset: {
      x: this.state.scrollY
     }
  }
}],{
   listener: event => {
       this.handleScroll(event);
   }})
}>
</ScrollView>
Fromwood
  • 506
  • 3
  • 6
9

According to this source code Animated.event traverses the objects passed as arguments of it until finds an instance of AnimatedValue.

Then this key (where the AnimatedValue has been found) is applied to the callback (onScroll) and the value at the key of the event passed to the scroll is assigned to this AnimatedValue.

In the code:

const animatedValue = useRef(new Animated.Value(0)).current;
...
onScroll={Animated.event(
  [{nativeEvent: {contentOffset: {y: animatedValue}}}]
)}

is the same as

const animatedValue = useRef(new Animated.Value(0)).current;
...
onScroll={({nativeEvent: { contentOffset: {y} }}) => {
  animatedValue.setValue(y);
}}

If your callback accepts more than one event (argument), then just put the mapping object at the needed index (thus the array as the argument of Animated.value.

onScroll={Animated.event(
  [
     {}, // <- disregard first argument of the event callback
     {nativeEvent: {contentOffset: {y: animatedValue}}} // <- apply mapping to the second 
  ]
)}


AlVelig
  • 1,989
  • 15
  • 9
4

Yes there is a difference in semantic

 <ScrollView onScroll={Animated.event(
  [{nativeEvent: {contentOffset: {y: this.state.scrollY}}}]
)}></ScrollView>

The first one i.e the above Animated.event returns a function that sets the scrollview's nativeEvent.contentOffset.y to your current scrollY state which I assume is animated.

The other code just sets scrollY to your scrollView's e.nativeEvent.contentOffset.y and causes a rerender to your component

kabangi julius
  • 2,709
  • 2
  • 16
  • 25