software-mansion / react-native-reanimated

React Native's Animated library reimplemented
https://docs.swmansion.com/react-native-reanimated/
MIT License
8.83k stars 1.29k forks source link

Can't scrollToOffset() FlatList when use with Animated.ScrollView #587

Closed ogous closed 4 years ago

ogous commented 4 years ago

When i use renderScrollComponent for Flatlist with a Animated.ScrollView:

renderScrollComponent={props => ( <Animated.ScrollView {...props} />

FlatList's scrollTo functions (like scrollToOffset) stop working.

Here is a re-pro: scrollToOffset becomes undefined

If you use it with a RN ScrollView everything works normally. It seems problem occurs when you use Animated component for renderScrollComponent. It is same with RN-Animated and RN-Reanimated.

Anybody have an idea about it?

Jarred-Sumner commented 4 years ago

Are you sure that the FlatList has mounted & set the ref?

ogous commented 4 years ago

@Jarred-Sumner yes you can see in the repro. If you toggle comment scrollToOffset line and toggle console.log(FlatListRef.current) line, ref is set to FlatList.

FlatListRef.current.scrollToOffset is normal function, problem occurs when you add params to that funciton. Function becomes undefined.

Jarred-Sumner commented 4 years ago

I bet it’s something to do with running it inside Animated.useCode

I’m definitely using one of the scrollTo functions in an Animated FlatList but not sure if it’s that one

On Sun, Jan 26, 2020 at 5:09 AM Oğuzhan Ali notifications@github.com wrote:

@Jarred-Sumner https://github.com/Jarred-Sumner yes you can see in the repro https://snack.expo.io/@cyborg/b220bf. If you toggle comment scrollToOffset line and toggle console.log(FlatListRef.current) line, ref is set to FlatList.

FlatListRef.current.scrollToOffset is normal function, problem occurs when you add params to that funciton. Function becomes undefined.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/software-mansion/react-native-reanimated/issues/587?email_source=notifications&email_token=AAFNGS3Y43WB5FYJSHNHQBTQ7WDRTA5CNFSM4KLRWR5KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEJ5TOGI#issuecomment-578500377, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAFNGSYBHHSAV5XXYMB5UBLQ7WDRTANCNFSM4KLRWR5A .

ogous commented 4 years ago

@Jarred-Sumner This is not about useCode. I updated the repro. You can see function is inside of useEffect. Situation is same scrollToOffset with scrollToIndex.

ogous commented 4 years ago

I’m definitely using one of the scrollTo functions in an Animated FlatList but not sure if it’s that one

@Jarred-Sumner if you could take a look at how you are able to use scrollTo functions with an Animated Flatlist, it can help.

Jarred-Sumner commented 4 years ago

@oguzhanali example code:

    this.flatListRef.current.scrollToOffset({
      animated,
      offset
    })

My FlatList wrapper:

import * as React from "react";
import { FlatList as RNFlatList, FlatListProps, Platform } from "react-native";
import {
  FlatList as GestureHandlerFlatList,
  ScrollView as _ScrollView
} from "react-native-gesture-handler";
import Animated from "react-native-reanimated";
import { createNavigationAwareScrollable } from "@react-navigation/native";
import hoistNonReactStatics from "hoist-non-react-statics";

export const ScrollView = createNavigationAwareScrollable(
  Animated.createAnimatedComponent(_ScrollView)
);

const FlatListComponent = Animated.createAnimatedComponent(
  GestureHandlerFlatList
) as RNFlatList<any>;

const _FlatList = React.forwardRef(
  ({ contentContainerStyle, contentInset, contentOffset, ...props }, ref) => {
    let _ref = React.useRef();

    React.useImperativeHandle(ref, () => _ref.current.getNode());

    if (Platform.OS === "ios") {
      return (
        <FlatListComponent
          contentInset={contentInset}
          contentOffset={contentOffset}
          contentContainerStyle={contentContainerStyle}
          {...props}
          ref={_ref}
        />
      );
    } else {
      return (
        <FlatListComponent
          contentContainerStyle={
            !contentContainerStyle && (contentInset || contentOffset)
              ? {
                  paddingTop: contentInset?.top || 0,
                  paddingBottom: contentInset?.bottom || 0
                }
              : contentContainerStyle
          }
          {...props}
          ref={_ref}
        />
      );
    }
  }
);

export const FlatList = hoistNonReactStatics(
  _FlatList,
  RNFlatList
) as React.ComponentType<FlatListProps<any>>;

FlatList.defaultProps = {
  ...(FlatList.defaultProps || {})
};

export default FlatList;
ogous commented 4 years ago

@Jarred-Sumner thanks for sharing your code. It is a very specific issue only for RN FlatList when use renderScrollComponent with an animated one. Tried it with GestureHandler FlatList and there is no problem. There are many alternatives to avoid this problem and this not directly related to Renimated lib; so I am going to close this one, keep open this one beacuse this is a bug afterall.

co2nut commented 4 years ago

@oguzhanali Appreciate if you could share your code using GestureHandler FlatList to accomplish this =)

maitham commented 4 years ago

@oguzhanali +1

machadolucasvp commented 4 years ago

@oguzhanali could you tell us some of the many workarounds you mentioned?

byteab commented 4 years ago

use this one instead add a getNode()

this.flatListRef.current.getNode().scrollToOffset({
      animated,
      offset
})
NxsHbb commented 2 years ago

For those who are still confused https://stackoverflow.com/a/64232399/8460578

TOPWN commented 1 year ago

this works https://stackoverflow.com/a/60375486/6124121