0

I faced an unordinary javascript functionality. Below, you will see React code (more precisely: useEffect hook) compiled to javascript.

 (0, _react.useEffect)(() => {
    console.log("Outside", socket);
    if (socket !== null && socket !== void 0 && socket.connected) {
      console.log("Inside", socket);
      setNewSocket(socket);
    }
  }, [props]); 

you can see two console.log's, one outside 'if' statement and one inside.

However, in browser I see only 'Outside' console.log regardless if socket appear or not:

enter image description here

When I removing last 'if' check (&& socket.connected), the statement passes, but socket object and its keys values does not match.

code:

 (0, _react.useEffect)(() => {
    console.log("Outside", socket);
    if (socket !== null && socket !== void 0 ) {
      console.log("Inside", socket);
      console.log("connected", socket.connected);
      setNewSocket(socket);
    }
  }, [props]); 

console.log: enter image description here

Problem is that as a result setNewSocket setting socket with bad values (with socket.connected: false) causes the socket not to work.

How can it be possible? Any ideas?

one more interesting functionality is this behaviour happens only when I going directly to the page where socket is used, exp.: https://myweb.com/tableWithSocket. However, if I go to the /home page and then to the /tableWithSoket via navigation menu, it seems to work ok. Also, when I resize my page via toggle device toolbar or when I close my navbar, it starts to work as well. In conclusion, it guess it starts to work when rerender happens

pawel_s
  • 295
  • 1
  • 2
  • 13
  • When you click that little arrow in the console, you read the current state of the object, not the state from when `console.log` happened. `console.log(socket.connect)` shows the value from the time when it was called, because booleans are passed by value, not by reference – Konrad Dec 13 '22 at 13:32
  • 1
    Does this answer your question? [Weird behavior with objects & console.log](https://stackoverflow.com/questions/23429203/weird-behavior-with-objects-console-log) – Konrad Dec 13 '22 at 13:34
  • 1
    make sense. I am wondering how can I fix it? I can't use `JSON.stringify` due to `Converting circular structure to JSON` and `Object.assign` will work only for object that contain primitive values only. – pawel_s Dec 13 '22 at 14:15
  • 1
    You can try using `structuredClone`, but why do you want to log this to the console in the first place? – Konrad Dec 13 '22 at 14:17
  • I don't want to console it, but the problem is that `setNewSocket` setting socket is without connection (socket.connection: false) what causes that socket not work in my app. Console is just for debugging – pawel_s Dec 13 '22 at 14:26
  • Why do you store your socket in the state? Also, you just have to wait so the socket will connect. – Konrad Dec 13 '22 at 14:29
  • and `structuredClone` does not work as well, throws error `failed to execute structuredClone`. I guess because of `circular structure` – pawel_s Dec 13 '22 at 14:30
  • Also, don't paste images of the code please – Konrad Dec 13 '22 at 14:31
  • I store it in useContext to avoid props drilling. My structure is like in this video: https://youtu.be/tBr-PybP_9c?t=5367, or very similar – pawel_s Dec 13 '22 at 14:33
  • Why don't follow the video then and instead try to make hacks with `useEffect`? https://github.com/WebDevSimplified/Whatsapp-Clone/blob/master/client/src/contexts/SocketProvider.js – Konrad Dec 13 '22 at 14:34
  • because it is microfrontend and the same table is implemented in two different apps. So socket is provided to that table via props. In one app all work perfectly, in another, this kind of problem appears. This table is like a npm package that accept some props, one of this props is socket – pawel_s Dec 13 '22 at 14:40
  • 1
    Still, checking for `socket.connected` in `useEffect` won't work, because change of that property won't trigger the effect – Konrad Dec 13 '22 at 16:02
  • Your right! I figured it out. Will show my solution asap – pawel_s Dec 14 '22 at 09:59

1 Answers1

1

As @konrad mentioned: "checking for socket.connected in useEffect won't work, because change of that property won't trigger the effect"

In other words, I can not put just props as a dependency here (props is an object that contain socket and some other values that was passed to component) and I can not even put a socket as a dependency because both of them are objects, what means they are reference type and dependency array contains a reference number that will not change even if object key/values will change.

So, I need to check specifically socket.connected value:

(0, _react.useEffect)(() => {
  if (socket !== null && socket !== void 0 && socket.connected) {
    setNewSocket(socket);
  }
}, [socket, socket !== null && socket !== void 0 && socket.connected]); 

React code would look like this:

useEffect(() => {
  if (socket?.connected) {
    setNewSocket(socket);
  }
}, [socket?.connected]);
pawel_s
  • 295
  • 1
  • 2
  • 13