I'm trying to connect to a websocket server in react but I have to get the connection config from an api. I can't find the right pattern to do that.
I need to:
- Get the config from the api using react-query
- Create a client when the config is available
- Save the client in a state
- Update the client when the config changes
- Disconnect from the client on unmount
I'm using MQTT.js here because I want to connect to a mqtt broker, but it's the same thing as websockets. I just want to find the right pattern
Here is some of my attempts:
import mqtt from "mqtt"
export function useMqttClient() {
const [client, setClient] = useState();
const { data: config } = useQuery(/* ... */);
useEffect(() => {
if(config && !client) {
setClient(mqtt.connect(config))
}
}, [config, client])
// ...
}
The problem with this approach is that it doesn't end the connection (client.end()
) when the component that uses useMqttClient
unmounts. As the result, it tries to reconnect with the same config when the user navigates back to the same page and that's a problem for us. Also it doesn't update the client when config changes.
import mqtt from "mqtt"
export function useMqttClient() {
const [client, setClient] = useState();
const { data: config } = useQuery(/* ... */);
useEffect(() => {
if(config && !client?.connected) {
setClient(mqtt.connect(config))
}
return () => client?.end()
}, [config, client])
// ...
}
This time I end the connection in the cleanup function but I end up in an infinite loop. client
is an instance of a class and config is an object so both of them could cause the infinite loop. But I don't know how to stop it.