title: No Ice Candidates gathering, peerConnection.iceGatheringState returns "complete" right away
body: <p>I've been stuck on this for a while now. My code is based on <a href="https://webrtc.org/getting-started/firebase-rtc-codelab" rel="nofollow noreferrer">https://webrtc.org/getting-started/firebase-rtc-codelab</a>. I basically just changed it to React and firebase realtime database instead of firestore. </p>
  
  <pre><code>const VideoRoom = () =&gt; {
    const config = {
      apiKey: xxx,
      authDomain: xxx,
      databaseURL: xxx,
      projectId: xxx,
      storageBucket: xxx,
      messagingSenderId: xxx,
      appId: xxx,
    };
  
    const rtcconfig = {
      iceServers: [
        {
          urls: [
            "stun:stun1.l.google.com:19302",
            "stun:stun2.l.google.com:19302",
          ],
        },
      ],
      iceCandidatePoolSize: 10,
    };
  
    const { roomId } = useParams();
  
    if (!firebase.apps.length) {
      firebase.initializeApp(config);
    }
  
    const db = firebase.database();
    const rooms = () =&gt; db.ref("rooms");
    const room = (roomId) =&gt; db.ref(`rooms/${roomId}`);
    const callerCandidates = (roomId) =&gt;
      db.ref(`rooms/${roomId}/callerCandidates`);
    const calleeCandidates = (roomId) =&gt;
      db.ref(`rooms/${roomId}/calleeCandidates`);
  
    const peerConnection = new RTCPeerConnection(rtcconfig);
    var localStream = new MediaStream();
    var remoteStream = null;
  
    var localVideo = useRef(null);
    var remoteVideo = useRef(null);
  
    room(roomId)
      .once("value")
      .then((snapshot) =&gt; {
        if (!snapshot.val()) {
          createRoom();
          return;
        }
        joinRoomById(roomId, snapshot.val());
      });
  
    useEffect(() =&gt; {
      peerConnection.addEventListener("icegatheringstatechange", () =&gt; {
        console.log(
          `ICE gathering state changed: ${peerConnection.iceGatheringState}`
        );
      });
  
      peerConnection.addEventListener("connectionstatechange", () =&gt; {
        console.log(`Connection state change: ${peerConnection.connectionState}`);
      });
  
      peerConnection.addEventListener("signalingstatechange", () =&gt; {
        console.log(`Signaling state change: ${peerConnection.signalingState}`);
      });
  
      peerConnection.addEventListener("iceconnectionstatechange ", () =&gt; {
        console.log(
          `ICE connection state change: ${peerConnection.iceConnectionState}`
        );
      });
    });
  
    const createRoom = async () =&gt; {
      console.log("create room");
      localStream.getTracks().forEach((track) =&gt; {
        console.log("adding localStream to peerConnection");
        peerConnection.addTrack(track, localStream);
      });
  
      peerConnection.addEventListener("icecandidate", (event) =&gt; {
        console.log("listening for icecandidate on peerConnection");
        if (!event.candidate) {
          console.log("final icecandidate");
          return;
        }
        console.log("callerCandidate written to database");
        callerCandidates(roomId).set(event.candidate.toJSON());
      });
  
      const offer = await peerConnection.createOffer();
      await peerConnection.setLocalDescription(offer);
      console.log("Offer created and added to peerConnection local description");
  
      const roomWithOffer = {
        offer: {
          type: offer.type,
          sdp: offer.sdp,
        },
      };
  
      await room(roomId).update(roomWithOffer);
      console.log("Offer written to room database document");
  
      peerConnection.addEventListener("track", (event) =&gt; {
        event.streams[0].getTracks().forEach((track) =&gt; {
          console.log(
            "listening for track on peerConnection and adding them to remoteStream"
          );
          remoteStream.addTrack(track);
        });
      });
  
      room(roomId).on("value", async (snapshot) =&gt; {
        console.log("listening for remote session in room database document");
        const data = snapshot.val();
        if (!peerConnection.currentRemoteDescription &amp;&amp; data &amp;&amp; data.answer) {
          console.log("Got remote description: ", data.answer);
          const rtcSessionDescription = new RTCSessionDescription(data.answer);
          await peerConnection.setRemoteDescription(rtcSessionDescription);
        }
      });
  
      calleeCandidates(roomId).on("value", (snapshot) =&gt; {
        console.log(
          "listening for remote ICE candidates in room/calleCandidates database document"
        );
        if (snapshot.val()) {
          snapshot.val().forEach(async (change) =&gt; {
            if (change.type === "added") {
              let data = change.doc.data();
              await peerConnection.addIceCandidate(new RTCIceCandidate(data));
            }
          });
        }
      });
    };
  };
  </code></pre>
  
  <p>I'm getting the roomId through react router, I left out the rest of the component for the sake of readability. </p>
  
  <p>The console returns following: </p>
  
  <p>create room<br>
  Signaling state change: have-local-offer<br>
  Offer created and added to peerConnection local description<br>
  ICE gathering state changed: complete<br>
  listening for icecandidate on peerConnection<br>
  final icecandidate<br>
  adding localStream to peerConnection<br>
  Offer written to room database document<br>
  listening for remote ICE candidates in room/calleCandidates database document<br>
  listening for remote session in room database document  </p>
  
  <p>In the about:webrtc firefox tab I can see that the offer was created succesfully but there arent any ice candidates</p>
  
  <p>Thanks in advance!</p>