admin管理员组

文章数量:1421461

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 />
);

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 />
);
Share Improve this question edited Dec 12, 2018 at 9:29 theAlse asked Dec 12, 2018 at 9:13 theAlsetheAlse 5,75713 gold badges73 silver badges114 bronze badges 1
  • 1 Possible duplicate of Updating an object with setState in React – Hardik Modha Commented Dec 12, 2018 at 9:16
Add a ment  | 

1 Answer 1

Reset to default 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
     }
  })    
})

本文标签: javascriptadding data to a dictionary in reactStack Overflow