Invalid hook call. Hooks can only be called inside the body of a functional component

211 views Asked by At

I am trying to create something like a background worker that monitors a database (RabbitMQ). If there is a new entry, it will notify the user in the UI.

I call my "background worker" from the appbar:

<AppBar>
    <BGWorker />
</AppBar>

This is my BGWorker.js

import { Notify } from 'Notify.ts';

const { Client } = require('@stomp/stompjs');

class BGWorker extends Component {
    componentDidMount(){
        this.client = new Client();
        this.client.configure({
            brokerURL: 'ws://192.168.1.5:15555/ws',
            connectHeaders:{
                login: "guest",
                passcode: "guest"
            },

            onConnect: () => {
                this.client.suscribe('exchange/logs', message => {
                    console.log(message.body);       //yes this does print out correctly
                    Notify(message.body, 'info');    //error here
            },
        });

        this.client.activate();
    }

    render(){
        return (
            <div/>
        );
    }
}

export default BGWorker

and this is my Notify function located in Notify.ts

import { useDispatch } from 'react-redux';
import { showNotification } from 'react-admin';

export const Notify = (msg:string, type:string='info') => {
    const dispatch = useDispatch();

    return () => {
        dispatch(showNotification(msg, type)); //this will call React-Admin's showNotification function
        //... and other stuff
    };
};

But I get a "Invalid hook call. Hooks can only be called inside the body of a functional component." whenever an entry comes in. How do I fix this? I read the react documentation and tried to use a custom hook but it doesn't work as well (not sure if I'm doing it correctly):

function useFoo(client){ 
    if(client !== undefined)
    {
        client.suscribe('exchange/logs', message => { //I get an 'Uncaught (in promise) TypeError: Cannot read property of 'subscribe' of undefined
            Notify(message.body, 'info');
        },
    }
}

class BGWorker extends Component {
    ...
    onConnect: useFoo(this.client);
    ...
}
1

There are 1 answers

0
Prateek Thapa On BEST ANSWER

In order to use hooks, you should convert your class into functional component. I assume you don't know about hooks and functional components.

This blog will help you understand the nuances of the conversion -> https://nimblewebdeveloper.com/blog/convert-react-class-to-function-component

Secondly, you need to know how hooks works. Refer to this -> https://reactjs.org/docs/hooks-intro.html

function BGWorker() {
  const dispatch = useDispatch();

  React.useEffect(() => {
       const client = new Client();
       client.configure({
            brokerURL: 'ws://192.168.1.5:15555/ws',
            connectHeaders:{
                login: "guest",
                passcode: "guest"
            },

            onConnect: () => {
                client.suscribe('exchange/logs', message => {
                    // dispatch your actions here
                    dispatch()
            }),
        });

        client.activate();
  }, []);

  return <div />
}

It is better if you read a few blogs and watch a few tutorials and understand hooks and functional components. And then try to solve your problem.

You may find your answer here and in the long run, you need to understand both of them.