Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] useScrollViewOffset not updating with Animated.FlatList RefreshControl #5777

Closed
jcalem opened this issue Mar 10, 2024 · 0 comments · Fixed by #5790
Closed

[Android] useScrollViewOffset not updating with Animated.FlatList RefreshControl #5777

jcalem opened this issue Mar 10, 2024 · 0 comments · Fixed by #5790
Labels
Platform: Android This issue is specific to Android Repro provided A reproduction with a snippet of code, snack or repo is provided

Comments

@jcalem
Copy link

jcalem commented Mar 10, 2024

Description

On Android, when the onRefresh and refreshing props are specified in an Animated.FlatList with useScrollViewOffset, the offset value does not get updated. When the props are commented out, the hook works as expected. This also works as expected on iOS.

Screen.Recording.2024-03-10.at.12.37.39.PM.mov

Steps to reproduce

  1. Open Snack link, use Android device
  2. Scroll down any amount on the FlatList
  3. Tap on an item, this will console.log the current FlatList offset
  4. View logs

Snack or a link to a repository

https://snack.expo.dev/@jcalem/android---usescrollviewoffset-with-refresh

Reanimated version

3.3.0

React Native version

0.72.10

Platforms

Android

JavaScript runtime

Hermes

Workflow

Expo Dev Client

Architecture

Fabric (New Architecture)

Build type

Debug app & dev bundle

Device

Real device

Device model

No response

Acknowledgements

Yes

@github-actions github-actions bot added Repro provided A reproduction with a snippet of code, snack or repo is provided Platform: Android This issue is specific to Android labels Mar 10, 2024
github-merge-queue bot pushed a commit that referenced this issue Apr 3, 2024
## Summary

Fixes #5777 

Currently `useScrollViewOffset` takes the viewTag to the underlying
ScrollView by calling `findNodeHandle` itself on animatedRef. This
doesn't take into consideration a ScrollView that's wrapped in another
view. When you specify `onRefresh` property that's what happens -
ScrollView becomes a child of another view. `useAnimatedRef` takes the
correct tag because it uses in this case `getScrollableNode` member
function of the component - but this logic isn't transferred to other
hooks that require the tag.

This PR adds a getter function to the object returned by
`useAnimatedRef`, so no function needing the tag should ever acquire it
by itself - instead it should use the getter method.

## Test plan

- [x] iOS

- [x] Android

- [x] Fabric

<details>
<summary>
Testing code
</summary>

```tsx
import React from 'react';
import {
  Text,
  Pressable,
  SafeAreaView,
  StyleSheet,
  Button,
  findNodeHandle,
} from 'react-native';
import Animated, {
  useAnimatedRef,
  useScrollViewOffset,
} from 'react-native-reanimated';

export default function App() {
  const animatedRef = useAnimatedRef<Animated.ScrollView>();
  const offset = useScrollViewOffset(animatedRef);
  const [refreshing, setRefreshing] = React.useState(false);

  function printOffset() {
    console.log('OFFSET VALUE');
    console.log(offset.value);
  }

  return (
    <SafeAreaView>
      <Button
        title="refresh"
        onPress={() => setRefreshing((oldState) => !oldState)}
      />
      <List
        animatedRef={animatedRef}
        printOffset={printOffset}
        refreshing={refreshing}
      />
    </SafeAreaView>
  );
}

const List = ({ animatedRef, printOffset, refreshing }) => {
  console.log('tag', findNodeHandle(animatedRef.current));
  return (
    <Animated.FlatList
      ref={animatedRef}
      refreshing={refreshing}
      onRefresh={() => console.log('refreshing')}
      onViewableItemsChanged={() => {
        printOffset();
      }}
      data={[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]}
      renderItem={({ _, index }) => <Item onPress={printOffset} id={index} />}
    />
  );
};

const Item = ({ onPress, id }) => {
  return (
    <Pressable onPress={onPress} style={styles.pressable}>
      <Text>{id}</Text>
    </Pressable>
  );
};

const styles = StyleSheet.create({
  pressable: {
    padding: 40,
    justifyContent: 'center',
    alignItems: 'center',
    borderWidth: 1,
    borderColor: 'red',
    backgroundColor: 'white',
  },
});
```

</details>

---------

Co-authored-by: szydlovsky <9szydlowski9@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Platform: Android This issue is specific to Android Repro provided A reproduction with a snippet of code, snack or repo is provided
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant