1

I'm working on this React app which uses websockets, first off, some background information:

I got a fooArray which the user can change with a hook, I got a socket which changes on mount. Now, I got the following code, the // foo array change listener is the one which I'm talking about. I included the other ones for easier understanding

// socket ref
const socket = useRef(null);

// foo array change listener
useEffect(() => {
  // this === null is there to prevent emitting on something that's null,
  // if another way is possible too, please let me know.
  if (socket.current === null) return;
  socket.current.emit('foos', JSON.stringify(fooArray));
}, [fooArray, socket.current]);

// socket connection on mount
useEffect(() => {
  socket.current = ioClient(WS_URI);
}, []);

Now the problem is, if I remove socket.current from the dependency array of the fooArray change listener, the useEffect hook won't execute and the emit event won't occur when the websocket is connected.

How would I use this to make socket.current become a part of the dependency array and not be unused..?

Thimma
  • 1,343
  • 7
  • 33
  • What do you mean by `socket.current` is unused/unnecessary? Is eslint telling you that? – cbr May 24 '20 at 19:14
  • @cbr Yes, ESLint is telling me that. – Thimma May 24 '20 at 19:14
  • You'll probably want to put the socket into `useState` instead - apparently `useRef` isn't really supposed to be used as a dependency of `useEffect`: https://github.com/facebook/react/issues/14387#issuecomment-503616820 – cbr May 24 '20 at 19:18
  • @cbr oh, didn't know, will probably change it. I saw it used somewhere on GitHub but it makes sense. Thanks! – Thimma May 24 '20 at 19:31

1 Answers1

1

useEffect Hooks are executed in the order in which they are written provided their dependency arrays cause them to run(ll useEffects hooks run on initial render)

Since you have initialised the socket in a useEffect which is written post the other useEffect using the socke, on initial render you won't have the socket instance.

Changing the order of useEffect will work for you

// socket ref
const socket = useRef(null);

// socket connection on mount
useEffect(() => {
  socket.current = ioClient(WS_URI);
}, []);

// foo array change listener
useEffect(() => {
  socket.current.emit('foos', JSON.stringify(fooArray));
}, [fooArray]);
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • 2
    Additionally, if there's intentions of changing `socket.current`, then it's best to store the socket with `useState` instead of `useRef` so that changes trigger re-renders and the useEffect hooks. – cbr May 24 '20 at 19:25