How to connect HiveMqtt to React app using mqtt package - reactjs

I am trying to connect my react application to HiveMQ using mqtt.js package but I am having this error.
This is the code I used
useEffect(() => {
const options: IClientOptions = {
protocol: "ws",
username: "myfirstdevice",
password: "qweqwe123",
};
const client = mqtt.connect('ws://8dedd20fc1164c8e9ce132a8a8359991.s1.eu.hivemq.cloud:8884', options);
// const client = mqtt.connect(options);
client.on('connect', function () {
console.log('Connected');
});
client.on('error', function (error) {
console.log("ERROR", error);
});
client.on('message', (topic,message,packet)=>{
console.log("RECEIVE", topic)
console.log("RECEIVE", message)
console.log("RECEIVE", packet)
});
}, []);

Port 8884 is for MQTT over Secure WebSockets
You'll need to change the URL to start with wss:// not ws://

Related

React/Socket.io chat app not working on heroku

I have a chat app I made using React for the frontend, DRF for the backend and I also have a node.js server within the React app for socket.io The issue is that the chat doesn't work basically (it works fine locally). When a message is sent it's not emitted and only shows up when I refresh since it's then pulled from the DB instead. I have gone through many threads on here for this issue but can't figure out what I'm doing wrong.
My server:
const server = require("http").createServer();
const io = require("socket.io")(server, {
cors: {
origin: "*",
},
});
const PORT = process.env.PORT || 5000;
const NEW_CHAT_MESSAGE_EVENT = "newChatMessage";
io.on("connection", (socket) => {
console.log('Client connected')
// Join a conversation.
const {roomId} = socket.handshake.query;
socket.join(roomId);
// Listen for new messages
socket.on(NEW_CHAT_MESSAGE_EVENT, (data) => {
io.in(roomId).emit(NEW_CHAT_MESSAGE_EVENT, data);
});
// Leave the room if the user closes the socket
socket.on("disconnect", () => {
socket.leave(roomId);
});
});
server.listen(PORT, (error) => {
if (error) throw error;
console.log(`Listening on port ${PORT}`);
});
Hook I made for the frontend:
const NEW_CHAT_MESSAGE_EVENT = "newChatMessage"; // Name of the event
const SOCKET_SERVER_URL = `https://<my-react-frontend>.herokuapp.com`;
export const useChat = () => {
const socketRef = useRef();
const {messages, setMessages, activeConvo, headerConvo, reloadSideBar, setReloadSideBar} = useActiveConvo()
const roomId = activeConvo
useEffect(() => {
console.log('useChat useEffect ran')
// Creates a WebSocket connection
socketRef.current = socketIOClient(SOCKET_SERVER_URL, {
query: {roomId},
});
// Listens for incoming messages
socketRef.current.on(NEW_CHAT_MESSAGE_EVENT, (message) => {
const incomingMessage = {
message: message.body,
created_by: localStorage.getItem('currentUserID'),
};
console.log('messages set in useChat useFfect')
setMessages((messages) => [...messages, incomingMessage]);
});
// Destroys the socket reference
// when the connection is closed
return () => {
socketRef.current.disconnect();
};
}, [roomId]);
// Sends a message to the server that
// forwards it to all users in the same room
const sendMessage = (messageBody) => {
socketRef.current.emit(NEW_CHAT_MESSAGE_EVENT, {
body: messageBody,
senderId: socketRef.current.id,
});
const fetchContents = {
message: messageBody,
created_by: localStorage.getItem('currentUserID'),
convo_id: activeConvo ? activeConvo : headerConvo
}
fetch(`https://<my-drf-backend>.herokuapp.com/api/save-message/`, authRequestOptions(('POST'), fetchContents))
.then(response => response.json())
.then(setReloadSideBar(reloadSideBar + 1))
.catch(error => console.log(error))
};
return {messages, sendMessage};
};
The issue in most of the threads appeared to be either still using the localhost url on the frontend or not using process.env.PORT in the server but it's still busted after fixing that. I also saw someone mention in another thread that the folder structure was the issue so I tried having the server file in the root of the react app and having it in it's own folder under "src", no dice.
In case anyone faces this same issue, I solved it by putting the server in a separate app on heroku

Working with websocket in ReactJS project

I am tying to implement socket connection in ReactJs, I have read there documentation for how to implement more than one namespace in socket and this is how I did it after following there instructions
import {Manager} from "socket.io-client";
export const manager = new Manager(process.env.REACT_APP_SOCKET_API, {
transports: ["websocket"],
reconnection:true,
autoConnect:true,
});
// add the namespace [namespace1,namespace2]
export const chatSocket = manager.socket("/namespace1");
export const notesSocket = manager.socket("/namespace2");
manager.open((err) => {
if (err) {
console.log("socket connection error", err);
} else {
console.log("socket connection succeeded");
}
});
now I am trying to use it like that in my react app is this right or I should use it in another way because I don't see any result from my console.log mehtod
useEffect(() => {
chatSocket.on('connect',() => {
console.log('connected socket chat')
})
notesSocket.on('connect',() => {
console.log('connected socket notes')
})
},[])

Socket.io and Next.Js

I am working on a project for an interview and have been asked to create a NextJS app using Socket.io for realtime chat. I have the chat functionality working, but one of my requirements is to have an area where a user can see a list of current users. While I've found examples for Express servers, I cannot seem to work out how to do this using Next's API system. I have two connected issues:
Maintaining a list of users with chosen display names (not just the socket id)
Accessing and returning a current user list whenever a user joins or leaves.
I haven't had any luck scanning the docs.
Here is the server function:
import { NextApiRequest } from 'next';
import { NextApiResponseServerIO } from '../../types/next';
import { Server as ServerIO } from 'socket.io';
import { Server as NetServer } from 'http';
export const config = {
api: {
bodyParser: false
}
}
export default async (req: NextApiRequest, res: NextApiResponseServerIO) => {
if (!res.socket.server.io) {
console.log("** New Socket.io server **")
// adapts the Next net server to http server
const httpServer: NetServer = res.socket.server as any;
const io = new ServerIO(httpServer, {
path: '/api/socketio'
})
io.on('connect', async (socket) => {
socket.join('main')
// where I plan to put the code to send a current list
})
io.on('disconnect', socket => {
socket.leave('main')
})
res.socket.server.io = io;
}
res.end();
}
And the related client code:
useEffect((): any => {
const url = process.env.NEXT_BASE_URL as string | "";
// connect to socket server
const socket = io(url, {
path: "/api/socketio",
});
// log socket connection
socket.on("connect", () => {
dispatch(connect(socket.id));
dispatch(updateId(socket.id))
});
//updates chat on message dispatch
socket.on("message", (message: IMsg) => {
dispatch(receive(message));
});
socket.on('updateUsersList', (users) => {
console.log("Is this the users", users)
})
//server disconnect on unmount
if (socket) return () => dispatch(disconnect(socket));
}, []);

React native custom host pusher connection

Can't seem to connect to pusher. I've been working in these for days and can't seem to connect to pusher. version 6.0.3
import Pusher from 'pusher-js/react-native';
componentDidMount() {
this.willFocusSubscription = this.props.navigation.addListener(
'willFocus',
() => {
try {
this.pusher = new Pusher('key', {
wsHost: 'host',
wsPort: 6001,
enabledTransports: ['ws'],
disableStats:true,
});
Pusher.log = (msg) => {
console.log('Pusher message ' + msg);
};
} catch (error) {
console.log('error', error)
}
this.group_channel = this.pusher.subscribe('groupchat.' + session_id);
this.pusher.connection.bind('GroupMessageSent', (data) => {
console.log('connected', data)
});
this.group_channel.bind('GroupMessageSent', (data) => {
console.log('data', data)
});
})
}
Pusher message Pusher : : ["Connecting",{"transport":"xhr_polling","url":"https://sockjs-4444.pusher.com:443/pusher/app/DOCKOTO_KEY?protocol=7&client=js&version=6.0.3"}]
https://snack.expo.io/#jsfit/pusher
I have checked the pusher is working fine for me on the localhost
the main reason I think is your ws ws://test.dockoto.com:6001
Laravel WebSockets default port 6001 as you know but you still need to open the port on the server.
Shared hosting I think you have to contact with you hosting provider to open the port if needed
EC2:
https://stackoverflow.com/a/56667321/13647574

Call Socket IO instance from a component or API route on NextJS

I'm trying to call to my socket server instance from an API Route endpoint for to send a broadcast to all the Socket IO clients when I save a new record in the database.
Socket IO is running properly in my NextJS server.
I've created a custom ./server/index.ts for to run the NextJS server and Socket.io server sharing the same port.
The clients connect successfully to Socket IO server. But now I would like that when from the browser call to an API route like this /api/save I can use my Socket IO server instance for to emit a broadcast.
But I don't know how to get an instance of Socket IO server from other files in the project.
Thank you.
./server/index.ts
import "reflect-metadata";
import { createServer } from 'http'
import { parse } from 'url'
import next from 'next'
import socketIo from "socket.io";
const port = parseInt(process.env.PORT || '3000', 10);
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const http = createServer((req, res) => {
const parsedUrl = parse(req.url!, true);
const { pathname, query } = parsedUrl;
if (pathname === '/a') {
app.render(req, res, '/a', query)
} else if (pathname === '/b') {
app.render(req, res, '/b', query)
} else {
handle(req, res, parsedUrl)
}
}).listen(port);
const ioServer = socketIo(http);
ioServer.on("connection", function (socket) {
console.log('An user has connected!');
socket.on('disconnect', function () {
console.log('An user has disconnected');
});
});
// tslint:disable-next-line:no-console
console.log(
`> Server listening at http://localhost:${port} as ${
dev ? 'development' : process.env.NODE_ENV
}`
);
});
You do not need to export the instance just create a function to perform the task in socket file and export the function and use it wherever you want.

Resources