score:1

Accepted answer

You are not only missing data from the dependency array of useEffect hook but you are also missing setConnections() function from the dependency array.

You can use useReducer hook to move the state update logic out of the useEffect hook.

const initialState = {
   data: { foo: [], bar: [] },
   connections: ["conn1", "conn2"]
} 

const reducerFunc = (state, action) => {
   switch(action.type) {
       case 'UPDATE_CONNECTIONS':
          let _tempConns = [...action.checkedFields];
          let _conns = [];
          _tempConns.forEach(tempConn => {
              if (state.data[tempConn] !== undefined) _conns.push(`update_${tempConn}`);
              else _conns.push(tempConn);
          });
          return { ...state, connections: _conns };
        default: 
          return state;
   }
};

const [myState, dispatch] = useReducer(reducerFunc, initialState);

const { checkedFields } = useContext(FieldContext); // ["foo", "moo"];

useEffect(() => {
    dispatch({ type: 'UPDATE_CONNECTIONS', payload: checkedFields });
}, [checkedFields]);

Since React makes sure that dispatch function won't change, you can omit it from useEffect hook's dependency array.

For details on how to use useReducer hook, see folowing links:

score:0

With your update, it seems that your socket never close. If your component unmount / remount, you add a new socket on background. And then on every updates, it fire all previous sockets.

Your socket hook should return a close socket function. (I guess, I never use socket directly)

  useEffect(() => {
  const _socket = io(WS_URI);
  _socket.on("info", data => {
    // some magic happens here to add to the `data` object which is not important for this question
  });
  setSocket(_socket);
  return () => {_socket.close();}
}, [])

(That's not the response of your answer but it can help :) )

score:1

Could try with useRef if you can get away with the following in your websocket and there are no other useEffects counting on the data reference

useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component.

// make `data` a ref object
// Pitfall: any changes to `data.current` will NOT be tracked 
const data = useRef({ foo: [], bar: [] })


// the websocket hook
useEffect(() => {
  ...
  _socket.on("info", data => {
    ...
    // update properties on `data.current`
    data.current.foo = 'some new value'
    data.current.bar = 'anoher new value;
  });
  
  ...
}, [])

useEffect(() => {
  setConnections(prevConnections => {
    ... 
    // reference data value from data.current
    const data = data.current

    ...
    return _conns;
  });
}, [checkedFields])


Related Query

More Query from same tag