Executing function in child component from parent

I’m using React Native, and I have a functional component that has a function in it. This child component is located inside another component, on that another component I have a button. So, When the user clicks the button, I want to execute the function in the child component.

I read about forwardRef (as I saw few questions about this that suggested this solution): https://reactjs.org/docs/forwarding-refs.html But it does not seems to fit my problem. I don’t need to access an element in my child component, only to execute the function.

This is my child component:

  const Popup = () => {
  const opacity = useRef(new Animated.Value(1)).current;
  const translationY = useRef(new Animated.Value(-120)).current;

  const {theme} = useContext(ThemeContext);

  const displayPopup = () => {
    Animated.spring(translationY, {
      toValue: 100,
      useNativeDriver: true,
    }).start();
  };

  return (
    <Animated.View
      style={[
        styles.container,
        {
          backgroundColor: theme.popup,
          opacity: opacity,
          transform: [{translateY: translationY}],
        },
      ]}>
     ...
    </Animated.View>
  );
};

Inside the parent component:

<SafeAreaView>
      // Other components
      <Popup />
      <Button onPress={() => {//NEEDS TO CALL displayPopup}}/>
</SafeAreaView>

Answer

Using a forward ref to give access to a child function can be a solution, but it’s not the React way to do it (See useImperativeHandle hook)

Instead, I would change a props of the Popup component to trigger the animation you want to use:

import { useEffect } from "react";

 const Popup = ({display = false}) => {
  const opacity = useRef(new Animated.Value(1)).current;
  const translationY = useRef(new Animated.Value(-120)).current;

  const {theme} = useContext(ThemeContext);

  useEffect(() => {
      if(display){
        Animated.spring(translationY, {
            toValue: 100,
            useNativeDriver: true,
        }).start();
      } 
  }, [display])

  return (
    <Animated.View
      style={[
        styles.container,
        {
          backgroundColor: theme.popup,
          opacity: opacity,
          transform: [{translateY: translationY}],
        },
      ]}>
     ...
    </Animated.View>
  );
};

Parent component:

const [display, setDisplay] = useState(false);

return(
   <SafeAreaView>
      // Other components
      <Popup display={display} />
      <Button onPress={() => {setDisplay(true)}}/>
    </SafeAreaView> 
)