1

I am using mqtt to receive some data and I would like to add that data directly to a dictionary.

My probably naive way to add the data to the dictionary is the following:

this.client.on('message', (topic, message) => {
  this.state.mqttMessage[topic] = message.toString();    
})

I also tried the following:

  this.setState(prevState => ({
    mqttMessage: {
        ...prevState.mqttMessage,
        topic: message.toString()
    }
  }))

But that adds the keyword "topic" to the dictionary.

The above line seems to generate the following warning as well:

Do not mutate state directly. Use setState()  react/no-direct-mutation-state

Later I would like to show what was received above, using this code:

  render() {
    console.log(this.props.mqttMessage)

return (
  <div>
      test1: {this.props.mqttMessage["test1"]} <br/>
      test2: {this.props.mqttMessage["test2"]} <br/>
      test3: {this.props.mqttMessage["test3"]} <br/>
  </div>
);

}

But the problem is that objects don't seem to get updated directly, I need ti refresh the page in order for the content to kick in. I guess I am not using the setState properly. The proper way of doing what I am trying to do would be appreciated.

Below is the whole code:

import React, { Component } from 'react';

import Button from 'react-bootstrap/lib/Button';
import Tab from 'react-bootstrap/lib/Tab';
import Tabs from 'react-bootstrap/lib/Tabs';

import 'rc-slider/assets/index.css';
import './App.css';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      mqttMessage: {}
    }

    this.mqtt = require('mqtt')
    this.client = this.mqtt.connect('mqtt://192.168.10.100:9001')

    this.client.on('connect', () => {
      this.client.subscribe('test1')
      this.client.subscribe('test2')
      this.client.subscribe('test3')
    })
    this.client.on('message', (topic, message) => {
      this.state.mqttMessage[topic] = message.toString();    
    })

  }

  render() {
    return (
      <div className="App">
        <Tabs defaultActiveKey="profile" id="uncontrolled-tab-example">
          <Tab eventKey="home" title="Home">
            <PostMessage client={this.client} />
          </Tab>
          <Tab eventKey="seats" title="Seats">
            <SeatPage mqttMessage={this.state.mqttMessage} client={this.client} />
          </Tab>
        </Tabs>

      </div>
    );
  }
}


class PostMessage extends React.Component {

  sendMessage = (e) => {
    e.preventDefault();
    this.props.client.publish('demo/test', 'My Message');
  }

  render() {
    return (
      <Button onClick={this.sendMessage}>
        Send Message
      </Button>
    );
  }
}


class SeatPage extends React.Component {

  sendMessage = (e, topic, message) => {
    e.preventDefault();
    this.props.client.publish(topic, message);
  }

  render() {
    console.log(this.props.mqttMessage)

    return (
      <div>
          test1: {this.props.mqttMessage["test1"]} <br/>
          test2: {this.props.mqttMessage["test2"]} <br/>
          test3: {this.props.mqttMessage["test3"]} <br/>
      </div>
    );
  }
}

export default () => (
    <App />
);
theAlse
  • 5,577
  • 11
  • 68
  • 110
  • 1
    Possible duplicate of [Updating an object with setState in React](https://stackoverflow.com/questions/43638938/updating-an-object-with-setstate-in-react) – Hardik Modha Dec 12 '18 at 09:16

1 Answers1

2

In react you shouldn't change state object directly. You should rather use setState method.

Something like below should do the trick.

this.client.on('message', (topic, message) => {
  this.setState({
     ...this.state,
     mqttMessage: {
         ...this.state.mqttMessage,
         [topic]: message
     }
  })    
})
Doğancan Arabacı
  • 3,934
  • 2
  • 17
  • 25
  • I almost tried that but with topic instead of [topic]. Can you explain the difference? – theAlse Dec 12 '18 at 09:26
  • 1
    New to javascript? :D if you use 'topic': 'some topic value', the string 'topic' is your key. If you use [topic]: 'some topic value', topic is a variable and it's value is your key – Doğancan Arabacı Dec 12 '18 at 09:34