ICE Candidate never fire

I want to develop a video call application using React Native and Java. Although the calling and answering events are happening, the onicecandidate function is never triggered, so the candidates are not working. Is there any error in my code, and if so, where is it? Thanks

I used
“react-native-webrtc”: “^111.0.3”,
“react”: “18.2.0”,
“react-native”: “0.71.6”,

/* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable no-undef */
import React, { useEffect, useRef, useState } from 'react';
import { View, Text, SafeAreaView, StyleSheet, LogBox, TouchableOpacity } from 'react-native'
import { NavigationContainer, StackActions } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

import AuthNavigator from './src/assets/navigations/AuthNavigator';
import OnboardingScreen from './src/screens/Onboarding/Onboarding';
import CallEnd from './src/components/CallEnd';
import CallAnswer from './src/components/CallAnswer';
import IconContainer from './src/components/IconContainer';
import CameraSwitch from './src/components/CameraSwitch';
import VideoOff from './src/components/VideoOff';
import VideoOn from './src/components/VideoOn';
import SocketIOClient from 'socket.io-client';
import InCallManager from 'react-native-incall-manager';
import RNRestart from 'react-native-restart';

import {
  mediaDevices,
  RTCPeerConnection,
  RTCView,
  RTCIceCandidate,
  RTCSessionDescription,
} from 'react-native-webrtc';
import MicOn from './src/components/MicOn';
import MicOff from './src/components/MicOff';
import { HOST } from './src/api/api';
import AsyncStorage from '@react-native-async-storage/async-storage';


LogBox.ignoreAllLogs();

function App() {
  const [auth, setAuth] = useState(false);
  const [localStream, setlocalStream] = useState(null);
  const [remoteStream, setRemoteStream] = useState(null);
  const [localMicOn, setlocalMicOn] = useState(true);
  const [localWebcamOn, setlocalWebcamOn] = useState(true);
  const [type, setType] = useState('JOIN');
  const [userId, setUserId] = useState(null);
  const [callerName, setCallerName] = useState(null);
  const [calleeName, setCalleeName] = useState(null);
  let remoteRTCMessage = useRef(null);
  let isFront = false;
  const [callerId, setCallerId] = useState("caller");
  const otherUserId = useRef(null);

  const setOtherUserId = (data) => {
    otherUserId.current = data.userId;
    setCalleeName(data.name)
  }

  const socket = SocketIOClient(HOST.websocket, {
    transports: ['websocket'],
    query: {
      callerId,
    },
  });

  const peerConnection = useRef(
    new RTCPeerConnection({
      iceServers: [
        {
          urls: 'stun:stun.l.google.com:19302',
        },
      ],
    }),
  );

  useEffect(() => {
    socket.on('newCall', data => {
      if (userId && data.calleeId == userId) {
        remoteRTCMessage.current = data.rtcMessage;
        otherUserId.current = data.callerId;
        setCallerName(data.callerName);
        setType('INCOMING_CALL');
      }
    });

    socket.on('newEnd', data => {
      if (userId && (data.user1 == userId || data.user2 == userId)) {
        peerConnection.current.close();
        RNRestart.Restart();
      }
    });

    socket.on('callAnswered', async data => {
      if (userId && (data.callerId == userId)) {
        remoteRTCMessage.current = data.rtcMessage;
        let message = new RTCSessionDescription(remoteRTCMessage.current);
        console.log(message);
        await peerConnection.current.setRemoteDescription(message);
        console.log(peerConnection);
        setType('WEBRTC_ROOM');
      }
      if (userId && (data.calleeId == userId)) {
        setType('WEBRTC_ROOM');
      }
    });

    socket.on('ICEcandidate', async data => {
      if (userId && (data.callerId == userId || data.calleeId == userId)) {
        let message = data.rtcMessage;
        if (peerConnection.current) {
          await peerConnection.current
            .addIceCandidate(
              new RTCIceCandidate({
                candidate: message.candidate,
                sdpMid: message.id,
                sdpMLineIndex: message.label,
              }),
            )
            .then(data => {
              console.log('SUCCESS');
            })
            .catch(err => {
              console.log('Error', err);
            });
        }
      }
    });
    mediaDevices.enumerateDevices().then(sourceInfos => {
      let videoSourceId;
      for (let i = 0; i < sourceInfos.length; i++) {
        const sourceInfo = sourceInfos[i];
        if (
          sourceInfo.kind == 'videoinput' &&
          sourceInfo.facing == (isFront ? 'user' : 'environment')
        ) {
          videoSourceId = sourceInfo.deviceId;
        }
      }

      mediaDevices
        .getUserMedia({
          audio: true,
          video: {
            mandatory: {
              minWidth: 500, // Provide your own width, height and frame rate here
              minHeight: 300,
              minFrameRate: 30,
            },
            facingMode: isFront ? 'user' : 'environment',
            optional: videoSourceId ? [{ sourceId: videoSourceId }] : [],
          },
        })
        .then(stream => {
          setlocalStream(stream);
          peerConnection.current.addStream(stream);
        })
        .catch(error => {
          // Log error
        });
    });

    peerConnection.current.onaddstream = event => {
      setRemoteStream(event.stream);
    };

    return () => {
      socket.off('newCall');
      socket.off('callAnswered');
      socket.off('ICEcandidate');
    };
  }, [userId, otherUserId]);

  useEffect(() => {
    InCallManager.start();
    InCallManager.setKeepScreenOn(true);
    InCallManager.setForceSpeakerphoneOn(true);

    return () => {
      InCallManager.stop();
    };

  }, []);

  function sendICEcandidate(data) {
    socket.emit('ICEcandidate', data);
  }

  async function callUser() {

    const sessionDescription = await peerConnection.current.createOffer();
    await peerConnection.current.setLocalDescription(sessionDescription);

    peerConnection.current.onicecandidate = async (event) => {
      await event;
      if (event.candidate) {
        await sendICEcandidate({
          callerId: userId,
          userId: userId,
          calleeId: otherUserId.current,
          type: "offer",
          rtcMessage: {
            label: event.candidate.sdpMLineIndex,
            id: event.candidate.sdpMid,
            candidate: event.candidate.candidate,
          },
        });
      }
    };

    sendCall({
      userId: userId,
      calleeId: otherUserId.current,
      rtcMessage: sessionDescription,
    });
  }

  async function callEnd(userId, otherUserId) {
    sendEnd({
      user1: userId,
      user2: otherUserId,
    });
    setType('JOIN');
  }

  async function callSave(userId) {
    sendSave({
      userId: userId,
      calleeId: null,
      rtcMessage: null,
    });
  }
  async function processAccept(otherUserId) {
    peerConnection.current.setRemoteDescription(
      new RTCSessionDescription(remoteRTCMessage.current),
    );
    const sessionDescription = await peerConnection.current.createAnswer();
    await peerConnection.current.setLocalDescription(sessionDescription);

    peerConnection.current.onicecandidate = async event => {
      await event;
      if (event.candidate) {

        await sendICEcandidate({
          callerId: otherUserId.current,
          userId: userId,
          calleeId: userId,
          type: "answer",
          rtcMessage: {
            label: event.candidate.sdpMLineIndex,
            id: event.candidate.sdpMid,
            candidate: event.candidate.candidate,
          },
        });
      }
    };

    answerCall({
      userId: userId,
      callerId: otherUserId.current,
      rtcMessage: sessionDescription,
    });
  }

  function answerCall(data) {
    socket.emit('answerCall', data);
  }

  function sendCall(data) {
    socket.emit('call', data);
    setType('OUTGOING_CALL');
  }

  function sendEnd(data) {
    socket.emit('end', data);
  }

  function sendSave(data) {
    socket.emit('save', data);
  }

  const OutgoingCallScreen = () => {
    return (
      <View
        style={{
          flex: 1,
          justifyContent: 'space-around',
          backgroundColor: '#050A0E',
        }}>
        <View
          style={{
            padding: 35,
            justifyContent: 'center',
            alignItems: 'center',
            borderRadius: 14,
          }}>
          <Text
            style={{
              fontSize: 16,
              color: '#D0D4DD',
            }}>
            Calling ...
          </Text>

          <Text
            style={{
              fontSize: 36,
              marginTop: 12,
              color: '#ffff',
              letterSpacing: 6,
            }}>
            {calleeName}
          </Text>
        </View>
        <View
          style={{
            justifyContent: 'center',
            alignItems: 'center',
          }}>
          <TouchableOpacity
            onPress={() => {
              callEnd(userId, otherUserId.current);
            }}
            style={{
              backgroundColor: '#FF5D5D',
              borderRadius: 30,
              height: 60,
              aspectRatio: 1,
              justifyContent: 'center',
              alignItems: 'center',
            }}>
            <CallEnd width={50} height={12} />
          </TouchableOpacity>
        </View>
      </View>
    );
  };

  const IncomingCallScreen = () => {
    return (
      <View
        style={{
          flex: 1,
          justifyContent: 'space-around',
          backgroundColor: '#050A0E',
        }}>
        <View
          style={{
            padding: 35,
            justifyContent: 'center',
            alignItems: 'center',
            borderRadius: 14,
          }}>
          <Text
            style={{
              fontSize: 36,
              marginTop: 12,
              color: '#ffff',
            }}>
            {callerName}
          </Text>
          <Text
            style={{
              fontSize: 16,
              color: '#D0D4DD',
            }}>
            is Calling..
          </Text>
        </View>
        <View
          style={{
            flexDirection: 'row',
            justifyContent: 'center',
            alignItems: 'center',
          }}>
          <TouchableOpacity
            onPress={() => {
              processAccept(otherUserId);
              setType('WEBRTC_ROOM');
            }}
            style={{
              backgroundColor: 'green',
              borderRadius: 30,
              height: 60,
              aspectRatio: 1,
              justifyContent: 'center',
              alignItems: 'center',
            }}>
            <CallAnswer height={28} fill={'#fff'} />
          </TouchableOpacity>
          <TouchableOpacity
            onPress={() => {
              callEnd(userId, otherUserId.current);
            }}
            style={{
              backgroundColor: '#FF5D5D',
              borderRadius: 30,
              height: 60,
              aspectRatio: 1,
              justifyContent: 'center',
              alignItems: 'center',
              marginLeft: 30,
            }}>
            <CallEnd width={50} height={12} />
          </TouchableOpacity>
        </View>
      </View>
    );
  };

  function switchCamera() {
    localStream.getVideoTracks().forEach(track => {
      track._switchCamera();
    });
  }

  function toggleCamera() {
    localWebcamOn ? setlocalWebcamOn(false) : setlocalWebcamOn(true);
    localStream.getVideoTracks().forEach(track => {
      localWebcamOn ? (track.enabled = false) : (track.enabled = true);
    });
  }

  function toggleMic() {
    localMicOn ? setlocalMicOn(false) : setlocalMicOn(true);
    localStream.getAudioTracks().forEach(track => {
      localMicOn ? (track.enabled = false) : (track.enabled = true);
    });
  }

  function leave() {
    peerConnection.current.close();
    setlocalStream(null);
    setType('JOIN');
  }

  const WebrtcRoomScreen = () => {
    return (
      <View
        style={{
          flex: 1,
          backgroundColor: '#050A0E',
          paddingHorizontal: 12,
          paddingVertical: 12,
        }}>
        {localStream ? (
          <RTCView
            objectFit={'cover'}
            style={{ flex: 1, backgroundColor: '#050A0E' }}
            streamURL={localStream.toURL()}
          />
        ) : null}
        {remoteStream ? (
          <RTCView
            objectFit={'cover'}
            style={{
              flex: 1,
              backgroundColor: '#050A0E',
              marginTop: 8,
            }}
            streamURL={remoteStream.toURL()}
          />
        ) : null}
        <View
          style={{
            marginVertical: 12,
            flexDirection: 'row',
            justifyContent: 'space-evenly',
          }}>
          <IconContainer
            backgroundColor={'red'}
            onPress={() => {
              leave();
            }}
            Icon={() => {
              return <CallEnd height={26} width={26} fill="#FFF" />;
            }}
          />
          <IconContainer
            style={{
              borderWidth: 1.5,
              borderColor: '#2B3034',
            }}
            backgroundColor={!localMicOn ? '#fff' : 'transparent'}
            onPress={() => {
              toggleMic();
            }}
            Icon={() => {
              return localMicOn ? (
                <MicOn height={24} width={24} fill="#FFF" />
              ) : (
                <MicOff height={28} width={28} fill="#1D2939" />
              );
            }}
          />
          <IconContainer
            style={{
              borderWidth: 1.5,
              borderColor: '#2B3034',
            }}
            backgroundColor={!localWebcamOn ? '#fff' : 'transparent'}
            onPress={() => {
              toggleCamera();
            }}
            Icon={() => {
              return localWebcamOn ? (
                <VideoOn height={24} width={24} fill="#FFF" />
              ) : (
                <VideoOff height={36} width={36} fill="#1D2939" />
              );
            }}
          />
          <IconContainer
            style={{
              borderWidth: 1.5,
              borderColor: '#2B3034',
            }}
            backgroundColor={'transparent'}
            onPress={() => {
              switchCamera();
            }}
            Icon={() => {
              return <CameraSwitch height={24} width={24} fill="#FFF" />;
            }}
          />
        </View>
      </View>
    );
  };

  switch (type) {
    case 'JOIN':
      return (
        <SafeAreaView style={styles.safeArea}>
          {auth ? (
            <View style={styles.conteiner}>
              <OnboardingScreen callUser={callUser} setOtherUserId={setOtherUserId} callSave={callSave} callUserId={setUserId} />
            </View>
          ) : (
            <NavigationContainer>
              <AuthNavigator callUser={callUser} setOtherUserId={setOtherUserId} callSave={callSave} callUserId={setUserId} />
            </NavigationContainer>
          )}
        </SafeAreaView>
      );
    case 'INCOMING_CALL':
      return IncomingCallScreen();
    case 'OUTGOING_CALL':
      return OutgoingCallScreen();
    case 'WEBRTC_ROOM':
      return WebrtcRoomScreen();
    default:
      return (
        <SafeAreaView style={styles.safeArea}>
          {auth ? (
            <View style={styles.conteiner}>
              <OnboardingScreen callUser={callUser} setOtherUserId={setOtherUserId} callSave={callSave} callUserId={setUserId} />
            </View>
          ) : (
            <NavigationContainer>
              <AuthNavigator callUser={callUser} setOtherUserId={setOtherUserId} callSave={callSave} callUserId={setUserId} />
            </NavigationContainer>
          )}
        </SafeAreaView>
      );
  }
}

export default App;
const styles = StyleSheet.create({
  conteiner: { flex: 1, justifyContent: 'center', alignItems: 'center' },
  safeArea: {
    flex: 1,
  },
});