Skip to content
This repository has been archived by the owner on Mar 24, 2023. It is now read-only.

Mqtt is stuck in connecting state in 2.0.0 version #13

Closed
Enigma10 opened this issue Jan 22, 2021 · 17 comments · Fixed by #18
Closed

Mqtt is stuck in connecting state in 2.0.0 version #13

Enigma10 opened this issue Jan 22, 2021 · 17 comments · Fixed by #18
Labels
help wanted Extra attention is needed

Comments

@Enigma10
Copy link

Enigma10 commented Jan 22, 2021

Screenshot from 2021-01-22 19-38-43

This is my connector code

@VictorHAS
Copy link
Owner

Did you have a console error? you can see if you are trying to connect to mqtt with the right protocol, like this?

image

@gggard
Copy link

gggard commented Jan 22, 2021

Hi there, I have the same issue and nothing bad in the logs ("New client connected from x.x.x.x as mqttjs_0773ea48 (c1, k0).")

@Enigma10
Copy link
Author

@VictorHAS I am getting this error when I am connecting SSR in nextjs but when I am loading this on clientside. it is working fine.

@VictorHAS VictorHAS added the help wanted Extra attention is needed label Jan 23, 2021
@coderantongmail
Copy link

And I have this problem. When connecting, you can see that instead of 1, the connection initializes 2, but the connection remains hanging. On the previous version, everything was ok. I also tried to use the example from the git, but the result is the same. Sorry for bad English

image

image

image

@VictorHAS
Copy link
Owner

VictorHAS commented Jan 26, 2021

I got some free time, I'll be looking for the solution for this. Sorry about anything, it's my first lib.

@coderantongmail thanks for providing images, could you send me how is your MQTT configuration?

-edit

@coderantongmail also you can import like this import { Connector, useMqttState } from 'mqtt-react-hooks'

@VictorHAS
Copy link
Owner

VictorHAS commented Jan 26, 2021

Can you guys try this please? @coderantongmail , @Enigma10 and @gggard
add 'keepalive' option in the Connector

<Connector brokerUrl="ws: //127.0.0.1: 1884" options={{ keepalive: 0 }} >

For some reason, using this option here connects normally

@coderantongmail
Copy link

Thank you @VictorHAS , Adding options={{ keepalive: 0 }} parameter to the helped to solve this problem.

But I also want to check how the library will behave if the broker stops responding, whether it will reconnect and change statuses.

@VictorHAS
Copy link
Owner

Thank you @VictorHAS , Adding options={{ keepalive: 0 }} parameter to the helped to solve this problem.

But I also want to check how the library will behave if the broker stops responding, whether it will reconnect and change statuses.

since this lib is a wrapper for Mqtt.js, it will automatically reconnect. https://github.com/mqttjs/MQTT.js#client for more informations

@coderantongmail
Copy link

coderantongmail commented Jan 28, 2021

If I have several components that are independent of each other, I add a subscription to a topic in the right component with the appropriate logic, but the component that was subscribed to another topic automatically receives all messages from all subscriptions. Is this normal behavior or was it intended a little differently?

If I disable broker status not changed to reconnecting, this is bug. And if broker run again, mqtt is reconnect, but status in connectionStatus not change if broker is down.

image

For example as in the screenshots below:

image

image

As a result, I had to do an additional check for the topic I needed, otherwise I received a bunch of unnecessary messages that should have been only in the diagnostic component.

After the second component has been destroyed, the subscription is saved all the same. It is necessary to make it possible to unsubscribe from the topic when the component is destroyed. More precisely, add the ability to unsubscribe in the library

@VictorHAS
Copy link
Owner

@coderantongmail since your comment is not directly related to this issue, I will create another one ok?

@coderantongmail
Copy link

@coderantongmail since your comment is not directly related to this issue, I will create another one ok?

Ok, thank`s @VictorHAS

@tom-con
Copy link

tom-con commented Sep 15, 2021

@VictorHAS Thanks for providing this library -- I am experiencing this issue on v2.0.2:
I tried adding options={{ keepalive: 0 }} to the Connector component but it still fails, I see that it is now a default for the prop, so I imagine that shouldn't matter whether it's included.
Initially I thought this is because I am using next.js with serverside rendering, however I disabled the connector on the server and it still remains in connecting on the client. I am successfully able to connect and receive messages on other clients. Any other thoughts as to why it might be failing?

@tom-con
Copy link

tom-con commented Sep 15, 2021

@VictorHAS Thanks for providing this library -- I am experiencing this issue on v2.0.2:
I tried adding options={{ keepalive: 0 }} to the Connector component but it still fails, I see that it is now a default for the prop, so I imagine that shouldn't matter whether it's included.
Initially I thought this is because I am using next.js with serverside rendering, however I disabled the connector on the server and it still remains in connecting on the client. I am successfully able to connect and receive messages on other clients. Any other thoughts as to why it might be failing?

Okay, I was being dumb but I'll leave this here to help future people!
I believed I was loading the Connector only on the clientside, however it was still being loaded on the serverside as well. I managed to fix this by doing this in the _app.js of next:

    { process.browser ? (
      <Connector brokerUrl={process.browser && process.env.NEXT_PUBLIC_MQTT_URL} options={{ keepalive: 0 }}>
        <Component {...pageProps} />
      </Connector>
    ) : (
      <Component {...pageProps} />
    )}

It's not ideal, but now I am connecting properly

@VictorHAS
Copy link
Owner

@tom-con thanks for reporting this, i will be pinning to help other people. If you know how to solve this problem in the package, can you create a PR? unfortunately, my time is tight to make adjustments.

@VictorHAS VictorHAS pinned this issue Sep 15, 2021
@VictorHAS
Copy link
Owner

@tom-con I just tested a new solution to this, with dynamic import and using ssr:false

import { AppProps } from 'next/app';
import '@/styles/global.css';

import dynamic from 'next/dynamic';

// i'll later export ConnectorProps
const Connector = dynamic<any>(
  () => import(`mqtt-react-hooks`).then((mod) => mod.Connector),
  { ssr: false },
);

export default function MyApp({ Component, pageProps }: AppProps) {
  return (
    <Connector
      brokerUrl="ws://test.mosquitto.org:8080"
      options={{ clientId: `testingMqttReactHooks` }}
    >
      <Component {...pageProps} />
    </Connector>
  );
}
import Head from 'next/head';
import Image from 'next/image';

import styles from '@/styles/Home.module.css';
import { useMqttState, useSubscription } from 'mqtt-react-hooks';

export default function Home() {
  const { connectionStatus } = useMqttState();
  const { message, client } = useSubscription(`mqtt/test`);
  return (
    <div className={styles.container}>
      <Head>
        <title>TypeScript starter for Next.js</title>
        <meta
          name="description"
          content="TypeScript starter for Next.js that includes all you need to build amazing apps"
        />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={styles.main}>
        <h1 className={styles.title}>
          Welcome to <a href="https://nextjs.org">Next.js!</a>
        </h1>

        <p className={styles.description}>
          Connection status{` `}
          <code className={styles.code}>{connectionStatus}</code>
        </p>

        <p className={styles.description}>
          new Message: {JSON.stringify(message)}
        </p>

        <div className={styles.grid}>
          <button
            type="button"
            className={styles.card}
            onClick={() => {
              client?.publish(`mqtt/test`, `This is a new message`);
            }}
          >
            <h2>Send Message &rarr;</h2>
            <p>send: This is a new message</p>
          </button>
        </div>
      </main>

      <footer className={styles.footer}>
        <a
          href="https://vercel.com?utm_source=typescript-nextjs-starter"
          target="_blank"
          rel="noopener noreferrer"
        >
          Powered by{` `}
          <span className={styles.logo}>
            <Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
          </span>
        </a>
      </footer>
    </div>
  );
}

image

@tom-con
Copy link

tom-con commented Sep 16, 2021

@VictorHAS This works great! Thank you for experimenting and finding this solution.

@tom-con
Copy link

tom-con commented Sep 16, 2021

@VictorHAS This works great! Thank you for experimenting and finding this solution.

Actually I just realized something -- this causes anything that is in the DOM tree beneath the dynamically imported component to not render until the import is complete on the client. If the Connector wraps the entire app, it will cause almost nothing to be server-side rendered, which is probably undesirable for people using Nextjs for SSR.

I suggest using a combination approach: keep both the dynamic import and the process.browser check. That way you get the benefit of not importing a package on the server when it's not needed, but also you are able to render a fully painted page before reaching the client.

Your example:

import { AppProps } from 'next/app';
import dynamic from 'next/dynamic';

const Connector = dynamic<any>(
  () => import(`mqtt-react-hooks`).then((mod) => mod.Connector),
  { ssr: false },
);

export default function MyApp({ Component, pageProps }: AppProps) {
  return (
     <Connector
        brokerUrl="ws://test.mosquitto.org:8080"
        options={{ clientId: `testingMqttReactHooks` }}
     >
        <Component {...pageProps} />
        {/* I won't be rendered on the server */}
     </Connector>
}

Suggestion:

import { AppProps } from 'next/app';
import dynamic from 'next/dynamic';

const Connector = dynamic<any>(
  () => import(`mqtt-react-hooks`).then((mod) => mod.Connector),
  { ssr: false },
);

export default function MyApp({ Component, pageProps }: AppProps) {
  return (
   { process.browser ? (
     <Connector
        brokerUrl="ws://test.mosquitto.org:8080"
        options={{ clientId: `testingMqttReactHooks` }}
     >
        <Component {...pageProps} />
        {/* I won't be rendered on the server */}
     </Connector>
   ) : (
        <Component {...pageProps} />
        {/* But I will be */}
   );
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants