0

I have onboarding and slide components . I am passing ref as a prop to slide component from onboarding component with forwardRef . It works fine but typescript gives me an error

My components are like below

const Onboarding = () => {
  const { width } = useOrientation();
  const scrollX = new Animated.Value(0);
  const scroll = useRef<Animated.ScrollView>(null);
  const onScroll = (event: any) => {
    Animated.event([{ nativeEvent: { contentOffset: { x: scrollX } } }]);
  };

  return (
    <Box flex={1}>
      <Animated.ScrollView
        ref={scroll}
        scrollEventThrottle={16}
        onScroll={onScroll}
        horizontal
      >
        {slides.map((data, index) => (
          <Slide key={index} data={data} ref={scroll} {...{ index, scrollX }} />
        ))}
      </Animated.ScrollView>
    </Box>
  );
};

interface SlideProps {
  data: {
    label: string;
    description: string;
    src: string;
  };
  scrollX: Animated.Value<0>;
  index: number;
}

export const Slide = forwardRef<Animated.ScrollView, SlideProps>(
  ({ data, scrollX, index }: SlideProps, ref) => {
    const { width, height } = Dimensions.get("window");

    const aspect = height / width;

    return (
      <Box flex={1} width={width} backgroundColor="mainBackground">
        <TouchableOpacity
          onPress={() =>
              //error here
            ref?.current?.getNode().scrollTo({ x: width * (index + 1), y: 0 })
          }
        >
          <Text>heyy</Text>
        </TouchableOpacity>
      </Box>
    );
  }
);

Error is like this; Property 'current' does not exist on type '((instance: ScrollView | null) => void) | MutableRefObject<ScrollView | null>'. How can I fix this issue ? Thanks.

1 Answer 1

1

To be honest, it feels weird to see the forwardRef in this context. I mean, what you really want is to have the ref referencing the Animated.ScrollView, not the Slide object.

Option 1 (ugly in my opinion): pass the ref as a property of Slide (not as the ref itself).

Option 2 (which I prefer): make Slide tell Onboarding that the press event happened and make Onboarding do the scrollTo

const Onboarding = () => {
  const { width } = useOrientation();
  const scrollX = new Animated.Value(0);
  const scroll = useRef<Animated.ScrollView>(null);
  const onScroll = (event: any) => {
    Animated.event([{ nativeEvent: { contentOffset: { x: scrollX } } }]);
  };
  const onPress = (width: number, index: number) => {
    scroll.current?.getNode().scrollTo({ x: width * (index + 1), y: 0 })
  }

  return (
    <Box flex={1}>
      <Animated.ScrollView
        ref={scroll}
        scrollEventThrottle={16}
        onScroll={onScroll}
        horizontal
      >
        {slides.map((data, index) => (
          <Slide key={index} onPress={onPress} data={data} {...{ index, scrollX }} />
        ))}
      </Animated.ScrollView>
    </Box>
  );
};

interface SlideProps {
  // same as before
  onPress: (width:number, index:number) => void
}

export const Slide = ({ data, scrollX, index, onPress }: SlideProps) => {
    const { width, height } = Dimensions.get("window");

    const aspect = height / width;

    return (
      <Box flex={1} width={width} backgroundColor="mainBackground">
        <TouchableOpacity
          onPress={() => onPress(width, index)}
        >
          <Text>heyy</Text>
        </TouchableOpacity>
      </Box>
    );
  }
);
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your answer.Why is forwardRef weird? Can you explain ? I want to comprehend it
Yes, sure! ForwardRef, as shown here: reactjs.org/docs/forwarding-refs.html, is when you want to forward a ref, created by the parent, to a single child. What you are trying to do is to share the ref between two children. If you see in your example, you create the scroll ref in Onboard component and forward that to Animated.ScrollView.
Thanks for your help it helped me a lot to understand

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.