ReactJS Hooks vs global variable

Viewed 1116

I'm having some trouble understanding hooks when there is no need to update the DOM, in my case it's a purely logic based requirement which I've solved with both hooks and global variables. This code represents a component of a simple peer to peer video conference application. In my case I'm saving calls retrieved from peerJS in a variable let calls = [] or with the hooks let [calls, setCalls] = useState({ calls: [], toClose: [] }) where the toClose are the calls that need to be closed. I'm then using the Effect hook to remove the calls based on the toClose variable. What is the best solution and why? Am I missing something about hooks, are they not supposed used in this kind of logic needs?

Hook Based:

...
let [calls, setCalls] = useState({ calls: [], toClose: [] })

useEffect(() => {
console.log(calls)
if (calls.toClose.length != 0) {
    setCalls((calls) => {
    return {
        calls: calls.calls.filter((call) => {
        if (calls.toClose.includes(call.peer)) {
            call.close()
            return false
        } else {
            return true
        }
        }),
        toClose: []
    }
    })

}
}, [calls])


peer.on('call', (call) => {
    ...
    setCalls((calls) => { return { calls: [...calls.calls, call], toClose: calls.toClose } })
})


socket.on('user-disconnected', id => {
    setCalls((calls) => { return { calls: calls.calls, toClose: [...calls.toClose, id] } })
    ...
})

socket.on('user-connected', (id) => {
    setCalls((calls) => { return { calls: [...calls.calls, call], toClose: calls.toClose } })
})
...

Global Variable based:


let calls = []

function Room(props) {
    ...
    peer.on('call', (call) => {
      ...
      calls.push(call)
    })

    socket.on('user-disconnected', id => {
      calls = calls.filter((call) => {
        if (call.peer == id) {
          call.close()
          console.log('Closed')
          return false
        } else {
          return true
        }
      })
    })

    socket.on('user-connected', (id) => {
        ...
        calls.push(call)
    })

    ...
  }
1 Answers

Thanks to @Drew Reese I've solved my problem by using a middle ground approach, I kept the out-of-react-scope variable but added another component that encapsulates my video, this will let me close the call once that component has unmounted.

import React, { useEffect, useState, useRef } from 'react';
import Video from './Video'
import './CallStream.css';

function CallStream({ call, stream }) {

    useEffect(() => {
        return () => {
            call.close()
        }
    }, [])

    return (
        <Video stream={stream}></Video>
    );
}

export default CallStream;
Related