Skip to content

Why is the condition in this callback always returns false?

I have a home SPA based on Vue. One of the components is driven by a v-if="isDisplayed“.

This isDisplayed is set by listening to a MQTT topic (see footnote) and new messages received are handled by the following function (I sepcifically used 'hello' instead of false to make sure the switch goes there). The topic of interest is display_school_edt.

mqttMessage(topic, message) {
      console.log(`App.vue received topic ${topic} with payload '${message}'`)
      if (topic === "dash/reload") {
        window.location.href = window.location.href
        document.location.reload(true);
      }
      if (topic === "dash/darkmode") {
        this.nightmode = JSON.parse(message) ? "night" : "day";
      }
      // this is the part I have problems with, I left everything for completness
      if (topic === "display_school_edt") {
        console.log(`edt display received: '${message}'`);
        if (message === 'on') {
          this.isEdtDisplayed = true
        } else {
          this.isEdtDisplayed = 'hello'
        }
        // I initially went for the ternary below - same results
        // message === "on" ? this.isEdtDisplayed = true : this.isEdtDisplayed = 'hello';
        console.log(`new edt display: ${this.isEdtDisplayed}`);
      }
    }

When I publish to the monitored topic display_school_edt (twice: one the message is on and the other time off), here is what I get on the console:

enter image description here

In other words, no matter if on or off is received, the condition is always false.

There is something obviously wrong with my code but the more I look, the better it looks.


Footnote: the fact that it is that specific protocol does not matter (it is a kind of bus often used with IoTs), you can assume that somehow mqttMessage() is executed with the parameters topic and message that are both strings.

Answer

This is indeed unexpected if message is of type string. However, it probably is not, and the only times you output message, you actually coerce it to string. So if you see from a previous output that it coerces to “no”, then in the if condition you should do the same, and force that conversion to string:

if (message+'' === 'no')

NB: This will call message.toString(), just like it does when you reference it within a template literal as ${message}.