react-native-circular-progress icon indicating copy to clipboard operation
react-native-circular-progress copied to clipboard

Can't pass reference from parent to child component using hooks

Open frankied003 opened this issue 3 years ago • 1 comments

Been trying to initiate the animation in the parent component using this code:

Parent component

import React, { useState, useEffect, useRef } from 'react';
import { ActivityIndicator } from 'react-native';
import {
  StyleSheet,
  Modal,
  TouchableOpacity,
  Animated,
  Easing,
  Alert,
  ScrollView,
  View,
} from 'react-native';
import MainTicketFillCard from '../../AppComponents/TicketFillComponents/mainTicketFillCard';
import CameraScreen from './cameraScreen';

import { Camera } from 'expo-camera';

fillDataTemplate = {
  name: "Bobcat Filler 3476",
  ticketId: "#5987234",
  gallons: 453,
  oilType: 'Diesel',
  additionalItems: 'None',
  imagePresent: false
}

const TankFillScreen = ({ navigation }) => {

  const [fillData, setfillData] = useState(null);
  const [gettingData, setgettingData] = useState(true);

  const [cameraOpen, setcameraOpen] = useState(false);
  const [picturePresent, setpicturePresent] = useState(fillDataTemplate.imagePresent);
  const [uploadingImage, setuploadingImage] = useState(false);
  let imageProgressRef;

  const openCamera = async () => {
    const { status } = await Camera.requestCameraPermissionsAsync();
    if(status === 'granted'){
      setcameraOpen(true)
    }
    else{
      Alert.alert(
        "No Camera Access",
        "To use this, please allow use of the camera",
        [
          {
          text: "Cancel",
          style: "cancel"
          },
          { text: "OK" }
        ]
      );
    }
  }

  const uploadImage = (uri) => {
    setcameraOpen(false);
    setpicturePresent(true);
    setuploadingImage(true);
    console.log("Uploading Image ", uri);
    print(imageProgressRef)
    imageProgressRef.animate(100, 8000, Easing.quad);
  }

  useEffect(
    () => {
      let timer = setTimeout(() => {
        setfillData(fillDataTemplate);
        setgettingData(false);
      }, 1000)
      return () => {
        clearTimeout(timer);
      }
    },
    []
  )

  return (
    <ScrollView>
      {cameraOpen
      ? (
        <Modal
        animationType="slide"
        transparent={true}
        visible={cameraOpen}
      >
        <CameraScreen close={() => setcameraOpen(false)} uploadImage={(uri) => uploadImage(uri)}/>
      </Modal>
      )
      : gettingData
        ? (
          <View style={styles.body}>
            <ActivityIndicator color="#000" />
          </View>
        )
        : (
          <View style={styles.body}>
            <MainTicketFillCard 
              data={fillData} 
              picturePresent={picturePresent}
              uploadingImage={uploadingImage}
              ref={imageProgressRef}
              openCamera={() => openCamera()}/>
          </View>
        )
      }
    </ScrollView>
  );
};

const styles = StyleSheet.create({
  body: {
    flex: 1,
    margin: 10
  },
  sectionTitle: {
    fontSize: 24,
    fontWeight: '600',
  }
});

export default TankFillScreen;

Child component

import React, { useEffect, forwardRef } from 'react';
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
import { Icon } from 'react-native-elements';
import SeperatorLine from '../GeneralComponents/seperatorLine';
import { AnimatedCircularProgress } from 'react-native-circular-progress';

const MainTicketFillCard = forwardRef((props, ref) => {

    useEffect(() => {
        
    }, [props.data])

    return (
        <View style={styles.outsideBody}>
            <View style={styles.flexSpaceRow}>
                <View style={{flexDirection: 'row'}}>
                    <AnimatedCircularProgress
                        ref={(thisRef) => ref = thisRef}
                        size={props.uploadingImage ? 20 : 0}
                        width={3}
                        fill={0}
                        tintColor="green"
                        backgroundColor="#ffffff" 
                    />
                    {props.picturePresent
                    ? (
                        <TouchableOpacity onPress={() => console.log("Open image")}>
                            <Icon
                                name='image' 
                                type='material-community' 
                                color='#000000'
                                size={25}
                            />
                        </TouchableOpacity>
                    )
                    : (
                        <TouchableOpacity onPress={() => props.openCamera()}>
                            <Icon
                                name='camera' 
                                type='material-community' 
                                color='#000000'
                                size={25}
                            />
                        </TouchableOpacity>
                    )
                    }
                </View>
            </View>
        </View>
    )
})

const styles = StyleSheet.create({
    outsideBody: {
        backgroundColor: '#ffffff',
        padding: 10,
        borderBottomLeftRadius: 10, 
        borderBottomRightRadius: 10,
        shadowColor: '#000',
        shadowOffset: { width: 0, height: 1 },
        shadowOpacity: 0.8,
        shadowRadius: 2,  
        elevation: 3
    },
    statusBar: {
        width: '100%',
        height: 10
    },
    insideBody: {
        flex: 1,
        padding: 10
    },
    flexSpaceRow: {
        flexDirection: 'row',
        alignContent: 'center',
        justifyContent: "space-between",
        marginBottom: 5
    },
    boldText: {
        fontSize: 18,
        fontWeight: 'bold',
        width: '70%'
    },
    boldTextNoWidth: {
        fontSize: 18,
        fontWeight: 'bold',
    }, 
    regText: {
        fontSize: 18,
        fontWeight: 'normal'
    },
    addressText: {
        fontSize: 15,
        color: "#414141", 
        marginBottom: 5
    },
    smallText: {
        fontSize: 12,
        marginTop: 5
    },
    statContainer: {
        flexDirection:'row',
        justifyContent: 'space-evenly',
        alignContent: 'center',
        margin: 10
    },
    singleStatContainer: {
        alignItems:'center'
    },
    statTitle: {
        fontSize: 18
    },
    statValue: {
        fontSize: 18,
        fontWeight: 'bold'
    }
});

export default MainTicketFillCard;

I thought that forwarding the ref would work, but I keep getting this error when i try to start the animation:

TypeError: Cannot read property 'animate' of undefined

frankied003 avatar Jan 31 '22 22:01 frankied003

same broo.. did you fix this .?

victorsamson1168 avatar Jun 06 '22 08:06 victorsamson1168