signalR connection.hub function not called in react component - reactjs

I'm creating a chatboard and I'm using signalR to let users know when new comment is added on some status/post.
I'm using React and I've tried to add event listeners for the hub function in different components, in some components it works, not others.
This is the hub:
public class CommentHub : Hub
{
public void UpdateComments(int postId)
{
try
{
var context = GlobalHost.ConnectionManager.GetHubContext<CommentHub>();
context.Clients.All.updateNewComments(postId);
}
catch (Exception ex)
{
Log.Error(ex.Message);
}
}
}
I call the event listener in the componentDidMound function:
componentDidMount: function() {
this.commentUpdateListener();
},
And this is the event listener:
commentUpdateListener: function () {
console.log("in the comment update listener!");
var commentHub = $.connection.commentHub;
commentHub.client.updateNewComments = function (postId) {
console.log("updateNewComments called!");
};
$.connection.hub.start();
},
I have a react component for a post/status, a component for the "wall/newsfeed" and then I have a component for the "comment box" for each status on the wall, where the comments are rendered.
When I place the event listener in the wall component or the post component it works, and the 'updateNewComponent' function gets called, but not when I place it in the "comment box" component.
Still "in the comment update listener!" gets logged no matter where I place the event listener, but the hub function is not always called, and it seems to matter in what react component the event listener is placed.
Is the $.connection.commentHub not staying alive? Is it closing?
Is there some reason the function is not always being called?

You can enable logging before starting the hub connection like this :
$.connection.hub.logging = true;
$.connection.hub.start();
If you see some disconnections you can try to restart the connection when it closes :
$.connection.hub.disconnected(function() {
setTimeout(function() {
$.connection.hub.start();
}, 5000); // Restart connection after 5 seconds.
});
Further reading : Understanding and Handling Connection Lifetime Events in SignalR

Related

CHROME -EXTENSIONS: How can I run message passing multiple times?

I am working on a project which produces a Chrome extension. In a background page I have a function named checkingProcess. This function is executed when a new tab is opened or a tab is updated. (I tried to catch the change of URL here.)
chrome.tabs.onActivated.addListener((activeInfo) => {
checkingProcess(activeInfo.tabId)
})
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
checkingProcess(tab.id)
})
Then, in the checkingProcess function, I have some functions for the data handling and API calls. Then I tried to receive a message that comes from popup. This message represents that the popup was opened by the user.
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.msg === 'popup_opened') {
sendResponse({
matches_length: response['matches'].length,
hostname: host,
})
}
chrome.runtime.lastError
})
After that, it sends a response to the popup. In the popup, I listen to the message and use the response in the popup.
useEffect(() => {
chrome.runtime.sendMessage({ msg: 'popup_opened' }, (res) => {
setHostname(res['hostname'])
setMatchesLength(res['matches_length'])
console.log(res['hostname'], 'burası')
console.log(res['matches_length'], 'burası')
})
}, [])
However, I realize that this message process is only executed once, but I need to run it multiple times to access the data in background simultaneously. How can I do that?
Your message is only sent once because it's currently setup in a React.useEffect with an empty list of dependencies. This means this code will only be run once when your component is mounted. If you want to run it "multiple times" you first need to define what this means? Examples are:
Executing sendMessage after a user performs some action, like clicking a button. In that case you don't need useEffect. Instead, wire an event handler to that button and perform the sendMessage there.
Executing sendMessage after re-render of your component. Simply remove the empty list of dependencies ([]) from your useEffect method. Note: use this with caution. If you setup your component in a way that it re-renders often, this can quickly turn into a situation where many API calls are made.
Executing sendMessage after some state within your component changes. Add this variable to the list of dependencies: [loaded]
Executing sendMessage every 10 seconds. You'll want to use setInterval within your useEffect, like this:
useEffect(() => {
const interval = setInterval(() => {
chrome.runtime.sendMessage({ msg: 'popup_opened' }, (res) => {
setHostname(res['hostname'])
setMatchesLength(res['matches_length'])
console.log(res['hostname'], 'burası')
console.log(res['matches_length'], 'burası')
})
}, 10000);
return () => clearInterval(interval);
}, []);

Figma React plugin PostMessage not working as expected

I'm trying to create a plugin for Figma, which has been going fine until now. It's based on the react example they provide on their github page: https://github.com/figma/plugin-samples/tree/master/react
In this example I've created a button, that on click will call this function:
(file: ui.tsx)
onClick = () => {
parent.postMessage({pluginMessage: {type: 'GetData'}}, '*');
};
This is parent.postMessage is a function figma provides to communicate with another file in the project, code.ts. This file will receive the postMessage with the pluginMessage as parameter, which works as expected. The code.ts that receives this looks like this:
(file: code.ts)
figma.ui.onmessage = msg => {
if (msg.type === 'GetData') {
figma.ui.postMessage({"title": figma.currentPage.selection[0].name});
}
};
This file receives the message, and it gets in the if statement since GetData has been set. Up until here, everything is good and well. The issue I'm walking into is the figma.ui.postMessage({}), which should do a callback to the onmessage function in ui.tsx:
(file: ui.tsx)
onmessage = (selection) => {
console.log(selection);
};
This onmessage function should, according to Figma's documentation, receive the object from the postMessage in code.ts. This does however never happen; it will never be called at all. I can't access the current selection in ui.tsx, so I need data from code.ts. Is there any way to pass this data to ui.tsx, or does anyone know why this doesn't work?
I encountered the same issue. Within your ui.tsx file, try adding the following:
window.onmessage = selection => {
let message = selection.data.pluginMessage;
console.log(message);
}
or try this ->
window.addEventListener("message", (selection) => {
console.log(selection);
});
this will add another message event handler to the window. if you use onmessage it might overwrite the previous handler!
put first of script
onmessage = event => {
console.log("got this from the plugin code", event, event.data.pluginMessage)
}

how to remove firebase.notifications().onNotificationOpened listener?

I am working on a react native project and using react-native-firebase library. Setting up listener is working but I am not able to find a way to remove listener.
I am setting up this listener on homepage so whenever user reach to homepage. Listener get registered multiple times and action multiple times as result.
I want to destroy this listener then again start a new one.
firebase.notifications().onNotificationOpened((notificationOpen) => {
if (notificationOpen) {
const notification: Notification = notificationOpen.notification;
if(notification.data.type){
}
}
});
If anyone can help, that will be appreciated...
You need to call the listener again in order to remove it as mentioned in the docs.
componentDidMount() {
this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen) => {
//... Your Stuff
}
}
componentWillUnmount() {
this.notificationOpenedListener();
}

Socket.io with React, server-to-client emit call not being received

I'm using React with Socket.io and trying to make my component update in real time, so one user can create a new event and it immediately shows up for all users. I've done this before outside of React, and it seems so simple, but I can't get it to work.
Desired behavior: When a user adds a new event, the server sends the new event to the client, where the client sets the new event into the redux store.
Actual behavior: The server emits the event, but the client never receives it. In the network tab, two websocket connections have status 'pending'.
This is my code:
server:
io.on('connection', (socket) => {
socket.on('createEvent', async (event, acknowledge) => {
let err;
let result;
// add event to DB
result = await db.createEvent(event);
if(!result) err = "An error occured during event creation.";
acknowledge(err, result);
console.log('result', result);
if (result) {
socket.emit('eventCreated', result);
console.log('emitted eventCreated');
}
});
});
Client:
componentDidMount () {
this.getEventsFromDB();
//listen for new events
socket.on ('eventCreated', (event) => {
console.log('hello,', event);
this.props.dispatch(addEvent({ event }));
});
};
I found the answer - I was using const socket = io() at the start of each file on the client side where I was using websockets. So each page was getting its own separate socket, which worked just fine until I needed two different pages to have access to the same socket.
I fixed it by instantiating one socket in my main file with my router, and passing it down to each component as a prop or via Redux.

SignalR doesn't push message to client

I am implementing functionality to notify the user of long running job completions using SignalR in an AngularJS application.I have created groups of user based on their name,so for each user a group of his name and different connectionids which he has opened up will be created and he would be notified by his group. I want to notify the user on two pages i.e. landing Page and Job Run Page as even if the user is on landing page and job run completes he should be notified of it.
For the same reason i am creating group by his name on both the pages,so that if he is on any page he would be nofied through the group.
On landing page controller js file i have written code to add the user in group as follow...
$rootScope.signalRHub = $.connection.signalRHub;
$rootScope.hubStart = null;
$rootScope.startHub = function () {
if ($rootScope.hubStart == null)
{
$rootScope.hubStart = $.connection.hub.start();
}
return $rootScope.hubStart;
}
$scope.$on('$locationChangeStart', function (event) {
if ($rootScope.userName != "") {
$rootScope.signalRHub.server.leaveGroup($rootScope.userName);
}
});
// Start the connection
$rootScope.startHub().done(function () {
$rootScope.signalRHub.server.joinGroup($rootScope.userName);
});
on Job Run controller js file i have written following code....
$rootScope.signalRHub.client.showNotification = function (message) {
notify('Your notification message');//notify is the angular js directive injected in this controller which runs fine
};
$scope.$on('$locationChangeStart', function (event) {
$rootScope.signalRHub.server.leaveGroup($rootScope.studyid);
});
// Start the connection
$rootScope.startHub().done(function () {
$rootScope.signalRHub.server.joinGroup($rootScope.userName
});
My Hub File.....
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class SignalRHub : Hub
{
public Task JoinGroup(string groupName)
{
return Groups.Add(Context.ConnectionId, groupName);
}
public Task LeaveGroup(string groupName)
{
return Groups.Remove(Context.ConnectionId, groupName);
}
public void ShowNotification(string jobRunDetailId, string userName)
{
if (!string.IsNullOrEmpty(userName))
{
var context = GlobalHost.ConnectionManager.GetHubContext<SignalRHub>();
context.Clients.Group(userName).showNotification(jobRunDetailId);
}
}
}
The issue is when i run the application the group add functionality for both pages works fine.but when i call "showNotification" from Hub it doesn't show any message.
But strange thing is if i comment the "$rootScope.startHub().done...." function on landing page then the jobrun page notify functionality works fine.I am not sure if writing "$rootScope.startHub().done()..." on two places is creating this problem.please help.
You need to wire up all callbacks before calling start. If you turn client side logging on, it'll tell you what hubs you are subscribed to.
Aside:
[EnableCors] is a webapi specific attribute that does not work in SignalR.

Resources