Claim
Claim

Reputation: 921

Can't use "this" in stomp client subscribe - React

I have my Spring-Boot service setup so I can send messages through websocket to my browser and it works.

  //@MessageMapping
    @RequestMapping(value = "/notify")
    @SubscribeMapping("/notification")
    @SendTo("/topic/notification")
    public String sendNotification() throws Exception {
        sendMessage();
        return "Request to update Tanks has been sent!";
    }

    public void sendMessage() {
        this.messagingTemplate.convertAndSend("/topic/notification", "IT WORKS");
    }

Here's the console log from chrome:

<<< MESSAGE
destination:/topic/notification
content-type:text/plain;charset=UTF-8
subscription:sub-1519225601109-13
message-id:f2qodiqn-8
content-length:8

IT WORKS

I want to be able to receive a message from the service and update the state in react, so, that it refetches from the backend. This is what my client looks like:

var socket = new SockJS("http://localhost:6667/refresh");
var stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
  console.log('connected: ' + frame);
  stompClient.subscribe('/topic/notification', function(notification){
    console.log(notification.body);
    //this.showNotification(JSON.parse(notification.body).content);
    //this.showNotification(notification.body);
  })
}, function(err) {
  console.log('err', err);
});

And the fetch in componentDidMount()

fetch(`http://localhost:6666/front/objects`)
    .then(result=>result.json())
    .then(fuelTanks=>this.setState({fuelTanks}))
    .catch(function(err) {
      console.log('Could not fetch: ' + err.message);
    }
  )

I can't use this.showNotification(notification.body), hence I can't set the state to be able to refetch my objects. I tried making methods outside the class but then I can't use anything from the main class.

Is there a way to make react run componentDidMount again, or better, just access the fetch method in my class when I get a message from spring through the websocket?

Like this:

componentDidMount(){

  var socket = new SockJS("http://192.168.1.139:8610/refresh");
  var stompClient = Stomp.over(socket);
  stompClient.connect({}, function(frame) {
    console.log('connected: ' + frame);
    stompClient.subscribe('/topic/notification', function(notification){
      refetchTanks(); // call fetch tanks -> can't use "this"
    })
  }, function(err) {
    console.log('err', err);
  });

Thanks!

Upvotes: 0

Views: 6897

Answers (2)

samairtimer
samairtimer

Reputation: 866

I know, it is a bit old question, but since it pops every time when you search for stomp issue, i thought of answering it. The way to access this in callbacks is to bind callbacks with this first, then the whole of object can be accessed in the callback. Example:

    connectCallBack(){
  this.setState({loading:false})

 }
 errorCallback=()=>{

 }

componentDidMount() {


axios.post('http://localhost:8080/subscribe', null, { params: {
deviceId
}})
.then(response => response.status)
.catch(err => console.warn(err));

const socket = new SockJS('http://localhost:8080/test');
const stompClient = Stomp.over(socket);

//stompClient.connect();
stompClient.connect( {}, this.connectCallBack, this.errorCallback);

If see above code both callbacks can access this.

Upvotes: 2

Claim
Claim

Reputation: 921

I tried everything to be able to use my class methods and the state in stompClient's .subscribe method. I was able to connect and reconnect if the service died, nevertheless it wasn't working.

I decided to use react-stomp, which worked. I could use a class method in onMessage=.... This is what my code looks like:

<SockJsClient 
  url = 'http://localhost:8610/refresh/'
  topics={['/topic/notification']} 
  onConnect={console.log("Connection established!")} 
  onDisconnect={console.log("Disconnected!")}
  onMessage={() => this.update()}  <------ this method performs a new GET 
                                           request
  debug= {true}
/> 

I also had to send the message in a specific way on the server side, since I was getting a JSON error when sending a string.

this.messagingTemplate.send("/topic/notification", "{"text":"text"}");

<<< MESSAGE
destination:/topic/notification
content-type:text/plain;charset=UTF-8
subscription:sub-0
message-id:aaylfxl4-1
content-length:49

{

  "text": "text"

}

It currently works, but I am curious if there are other, better solutions to this issue.

EDIT: a much better solution here! Use the code from the first post and create a variable before connect to be able to access this like this var self = this;, then just access is as self.update() after subscribe!

Upvotes: 1

Related Questions