Adam Gina
Adam Gina

Reputation: 63

Invalid hook call - React Redux

I'm trying to implement a static method to make my code cleaner. It has worked fine until I tried to do this:

// Auth.js
import {useDispatch} from 'react-redux';
import {signOut} from './redux_actions';

export class Auth {
    static signOut = () => {
        const dispatch = useDispatch();
        dispatch(signOut())
    }
}

// Menu.js
import {Auth} from '../../auth'
...
...
<MenuItem onClick={() => {Auth.signOut()}}><ExitToAppIcon className="icon"></ExitToAppIcon><span>log out</span></MenuItem>

However I get an error:

Invalid Hook call, You might have mismatching versions of React and React DOM.
You might be breaking the Rules of Hooks.
You might have more than one copy of React in the same app

I don't really know what I'm doing wrong. Probably i still don't really get the architecture. Thanks for your help!

EDIT:

according to the accepted answer, this worked

import { myStore } from './index'

export default class Auth {
    static signOut = () => {
        myStore.dispatch(signOut())
    }
}

Upvotes: 0

Views: 1637

Answers (3)

Olivier Boiss&#233;
Olivier Boiss&#233;

Reputation: 18113

Here are the rules of React Hooks :

  • Call Hooks from React function components
  • Call Hooks from custom Hooks

It seems that your are calling the hook useDispatch from an external function (nor a function component neither a customHook), that's why you get this error.

You can call const dispatch = useDispatch(); dispatch(signOut()); inside your component or if you really want to keep the Auth class, you can call the dispatch function directly from the store (without using the hooks) like this :

 import store from './path/to/your/store'

 export class Auth {
   static signOut = () => {
     store.dispatch(signOut())
   }
 }

Upvotes: 1

marzelin
marzelin

Reputation: 11600

You can't use useDispatch or any other hook in an event handler. Hooks can only be used in top level.

This should work:

export class Auth {
    static useSignOut = () => {
        const dispatch = useDispatch();
        return () => dispatch(signOut())
    }
}

// Menu.js
import {Auth} from '../../auth'
...
...
const signOut = Auth.useSignOut(); // now `useDispatch` is called at top level
<MenuItem onClick={signOut}><ExitToAppIcon className="icon"></ExitToAppIcon><span>log out</span></MenuItem>

Upvotes: 1

JeromeBu
JeromeBu

Reputation: 1159

You are trying to use a react hook in a class. This is not possible.

You have to be in a functional component to use hooks.

If you need to use a class, you can connect your component with the connect() HOC.

Upvotes: 1

Related Questions