mqtt-react-hooks icon indicating copy to clipboard operation
mqtt-react-hooks copied to clipboard

useSubscription resubscribes on each message received

Open Aposhian opened this issue 3 years ago • 6 comments

If I make a very simple component that displays data from a subscription, I have found that it resubscribes every time it receives a new message. This is inefficient, and causes extra latency. My guess is that because the Mqtt client is passed through the context, message receipt changes the client, which then causes the consumers of the mqtt context to rerender. I am looking into this right now.

Aposhian avatar May 23 '22 21:05 Aposhian

Actually, I think the real reason is that useSubscription creates a useEffect that calls subscribe that gets called every time the component gets rerendered. I think the intent is that subscribe is a useCallback, so it should be memoized, but that doesn't actually prevent subsequent calls to subscribe: it just memoizes the passing of the particular topic and options parameters.

Aposhian avatar May 23 '22 21:05 Aposhian

Hey @Aposhian thanks again for the contribution, I was doing some testing on the alpha version and there is a big problem with webpack 5 and react too. what configuration are you using now? I think we can use precompiled-mqtt for temporary solution, what you think? I'll do some tests with you new createSubscription

VictorHAS avatar May 24 '22 21:05 VictorHAS

I have been getting it to work with Webpack 5 by replacing Create React App with react-app-rewired, and then using the following Webpack overrides:

const webpack = require('webpack');
const path = require('path')

module.exports = function override(config) {
  const fallback = config.resolve.fallback || {};
  Object.assign(fallback, {
    "crypto": require.resolve("crypto-browserify"),
    "stream": require.resolve("stream-browserify"),
    "assert": require.resolve("assert"),
    "http": require.resolve("stream-http"),
    "https": require.resolve("https-browserify"),
    "os": require.resolve("os-browserify"),
    "url": require.resolve("url")
  })
  config.resolve.fallback = fallback;
  config.plugins = (config.plugins || []).concat([
    new webpack.ProvidePlugin({
      process: 'process/browser',
      Buffer: ['buffer', 'Buffer']
    })
  ])
  config.module.rules = (config.module.rules || []).concat([
    {
      test: /\.m?js/,
      resolve: {
        fullySpecified: false
      }
    }
  ])
  return config;
}

Aposhian avatar May 24 '22 22:05 Aposhian

Hey @Aposhian thanks again for the contribution, I was doing some testing on the alpha version and there is a big problem with webpack 5 and react too. what configuration are you using now? I think we can use precompiled-mqtt for temporary solution, what you think? I'll do some tests with you new createSubscription

Paho-MQTT seems to not have issues, but it would require switching libraries.

Dyocius avatar May 31 '22 21:05 Dyocius

Paho MQTT (for JavaScript) appears to not be actively maintained though: it hasn't had a commit in 3 years.

Aposhian avatar May 31 '22 21:05 Aposhian

Also, MQTT.js can be made to work just fine with Webpack 5: it just involves readding the polyfills that were removed by default.

Aposhian avatar May 31 '22 21:05 Aposhian