1

I am working on a React Native mobile chat application utilizing laravel-echo library for socket connections.

I have a function based EchoServer component, rendered from a custom header component on every page. It calls handleNewMessage through useEffect hook and sets a new Echo object for listening to sockets.

let echo = new Echo({
   broadcaster: 'socket.io',
   client: socketio,
   authEndpoint: constants.echoServer +  '/broadcasting/auth',
   host: constants.echoServer + ':' + constants.echoServerPort,
   auth: {
      headers: {
         Accept: "application/json",
         Authorization: `Bearer ${params.access_token}`,
      }
   },
});

 echo
     .private(channel)
     .notification((notification) => {
          handleNewMessage(notification);
     });

     console.log('Join "online" channel');
     echo.join('online')
         .here(users => {
              if(users.find(data => data.id === params.user.id)) {
                  setState({
                       icon: ICONS.online,
                       color: COLORS.online
                  });
              }
          });

     echo.connector.socket.on('subscription_error', (channel, data) => {
          console.log('channel subscription error: ' + channel, data);
     });

I do not have any issues with listening notifications from the socket connection. However, since this component is rendered in a header component as mentioned above, it also creates a new connection every time the header is rendered. That causes same notifications to come multiple times increasingly (At first I receive 1 notification, then 2 and 3 etc.)

I solved that problem by using a useContext hook for the echo object. I basically used the useContext hook as a global variable.

After,

const [ socket, setSocket ] = useContext(SocketContext);

I check if socket already has a value or not, before creating a "new Echo" object.

if (socket){
   return;
}

However, with this solution I had to add another context in my parent App.js file such that:

<AuthContext.Provider value={authContext}>
   <SocketContext.Provider value={[socket, setSocket]}>
     <MessageStore>
       <NavigationContainer>
       { user.access_token? 
         <MenuStack/>
       :
         <AuthStack/>
       }
       </NavigationContainer>
     </MessageStore>
   </SocketContext.Provider>
</AuthContext.Provider>

I can see that nested contexts might be an issue in future (if they're not already) as I already have 3. What I'd like to ask is, is there a better solution in order to check if socket connection has been established without using useContext hook?

I was also thinking maybe useContext is not the best solution for this.

Also establishing the socket connection right after the authentication process only once might be a better solution, instead of checking it every time in the header.

I am looking for suggestions about the best practices for this case.

Thank you for your helps in advance.

brsdncr
  • 31
  • 6

0 Answers0