I am developing mqtt web client for an IOT project using NextJs and mqtt package. In order to allow the client object to be shared among all components, I implemented a context API in which I defined some states as seen in the code below. The issue I am having here is, anytime I make update to msg
state using setMsg
function in the 'message' event handler, the msg does not get updated.
If I also try to publish a message by clicking a button, the message is not published. The only I was able to publish is by calling the client.publish
intermittently inside setInterval
I am using the shiftr.io mqtt broker and I see an error stating that connection failed even though the shiftr.io dashboard indicated that connection is established by showing the client with its ID.
Thank you in advance.
** index.js file:**
import Car from '../components/Car';
import CarList from '../components/CarList';
import Board from '../components/Board';
import Notification from '../components/Notification';
import { useState, useEffect } from 'react';
import { useGlobalContext } from '../lib/context';
import mqtt from 'mqtt'
import Head from 'next/head'
export default function Home() {
// console.log(JSON.parse(client).connected)
const client = mqtt.connect('mqtt://tatwo:[email protected]', {
clientId: 'client1'
})
const [freeSpace, setFreeState] = useState(1)
const {setSpaceStatus, setMqttClient, mqttClient, setMsg, msg} = useGlobalContext()
const [spaceMessageString, setSpaceMessageString] = useState(['0','0','0'])
const publishStatus = (msg, clt)=>{
client.publish('/reservation', msg)
}
if(client){
setMqttClient(client)
}
client.on('connect', function(){
console.log('connected')
client.subscribe('space')
})
client.on('message', function(topic, message){
console.log('receieved: ', message.toString().split(','))
// setSpaceMessageString(message.toString().split(','))
setMsg(message.toString())
// setSpaceStatus(message.toString().split(','))
})
useEffect(() => {
return ()=>{
if(mqttClient){
mqttClient.end()
}
}
}, [spaceMessageString])
return (
<div className='flex flex-col items-center justify-center'>
<h1 className='text-white text-3xl md:text-5xl font-extrabold text-center'>Parking without stress</h1>
<p className='text-amber-500 text-lg my-5'>Use smart parking system to check for parking space before you drive. </p>
<Board />
<p>{msg}: {mqttClient?.connected == true ? 'Onlined': 'offline'}</p>
{
freeSpace === 0 ?
// <Notification /> : <CarList spaceMessageString={spaceMessageString} />
<Notification /> : (
<div className='grid grid-cols-1 md:grid-cols-3 gap-4 my-5 w-full'>
{
spaceMessageString.map((space, index)=>
<Car
name={`Space ${index + 1}`}
message={spaceMessageString[index]}
key={index}
identity={index + 1}
publishStatus={publishStatus}
/>
)
}
</div>
)
}
</div>
)
}
** context.js: **
import React from 'react'
import { createContext, useContext, useState } from 'react'
const AppContext = createContext({});
const AppProvider = ({children}) => {
const [user, setUser] = useState(null)
const [reservations, setReservations] = useState([])
const [spaceStatus, setSpaceStatus] = useState([1, 0, 0])
const [connected, setConnected] = useState(false)
const [mqttClient, setMqttClient] = useState(null)
const [msg, setMsg] = useState('no message')
const client = null;
return (
<AppContext.Provider value={
{
user,
setUser,
spaceStatus,
setSpaceStatus,
reservations,
setReservations,
connected,
setConnected,
client,
setMqttClient,
mqttClient,
setMsg,
msg
}
}>
{children}
</AppContext.Provider>
)
}
export const useGlobalContext = () => useContext(AppContext);
export default AppProvider
** _app.js: **
import Layout from '../components/Layout'
import '../styles/globals.css'
import AppProvider from '../lib/context';
export default function App({ Component, pageProps }) {
return (
<AppProvider>
<Layout>
<Component {...pageProps} />
</Layout>
</AppProvider>
)
}
ws://
due to being run in the browser.