Rafael Tavares
Rafael Tavares

Reputation: 6471

How to create a close animation in a custom renderer component using react-native-popup-menu?

I am using the react-native-popup-menu and created my own renderer component. It's a function component, so in short it looks like this:

const ContextMenuRenderer = ({ children, layouts, ...otherProps }) => {
  return (
    <Animated.View
      {...otherProps}
      onLayout={handleViewLayout}
      style={[styles.viewStyle, viewAnimations]}
    >
      {children}
    </Animated.View>
  );
}

viewAnimations contains the opening animations, the code is relatively large but you can see it in this snack.

The docs says "In order to handle asynchronous closing animations, renderer can implement close()method which is called before menu closes. close method has to return Promise."

I read the ContextMenu code, it is a class component and implements close() as:

close() {
  return new Promise(resolve => {
    Animated.timing(this.state.scaleAnim, {
      duration: CLOSE_ANIM_DURATION,
      toValue: 0,
      easing: Easing.in(Easing.cubic),
      useNativeDriver: USE_NATIVE_DRIVER,
    }).start(resolve);
  });
}

I tried to implement something similar inside my Function Component but the code isn't executed. I figured it wouldn't work, but what can I do to create an animation on close? I wanted to do a fade out animation.

function close() {
  console.log('close'); // It isn't logged
  return new Promise((resolve) => {
    console.log('resolve close');
  });
}

Upvotes: 1

Views: 785

Answers (1)

sodik
sodik

Reputation: 4683

To allow your renderer to start closing animation, RN popup method calls imperative method close via ref.

The safest way (in terms it is also used and proven by the library) is use class components for that (as you already found).

The other option might be to use hooks useImperativeHandle together with forwardRef. Something like

function FancyRenderer(props, ref) {
  useImperativeHandle(ref, () => ({
    close: () => {
      return new Promise(...);
    }
  }));
  return <View>;
}
FancyRenderer = forwardRef(FancyRenderer);

I remember we are trying to check somehow if we can get the ref in the first place, so I am not sure if you would work as it was coded before the hooks and we have never tried it that way. Maybe small PR would be needed in such case.

Upvotes: 1

Related Questions