Marcos Freitas
Marcos Freitas

Reputation: 149

I'm Receiving Invalid Hook Call error either from inside a functional component

In my project I have the index.tsx calling the App.tsx that uses a UserProvider and AuthProvider. I received an invalid call error from inside the UserProvider because I'm using the useState hook.

This problem occurs also if I create a custom hook, I can't use any hook inside the custom hook.

This is my index.tsx:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
//import './commons/global.css';
import reportWebVitals from './reportWebVitals';

import App from './App';
import { BrowserRouter } from 'react-router-dom';

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('root'),
);

reportWebVitals();

This is my App.tsx:

import { useEffect, useState } from 'react';
import { BrowserRouter, useNavigate } from 'react-router-dom';
import {
  AuthService,
  AuthProvider,
  useAuth,
  useLogin,
  UserProvider,
} from 'reactjs-oauth2-pkce-provider';

import './index.css';
import Routes from './routes';

const authService = new AuthService({...});

const App = () => {
  const [user, setUser] = useState({});
  const [loading, setLoading] = useState(true);

  // for every refresh of the page, check if there is a user in localStorage
  useEffect(() => {
    const user = localStorage.getItem('user');

    if (user) {
      setUser(JSON.parse(user));
    }

    setLoading(false);
  }, []);

  return (
    <UserProvider>
      <AuthProvider authService={authService}>
        <Routes />
      </AuthProvider>
    </UserProvider>
  );
};

export default App;

This is my UserProvider.tsx:

import React, { ReactElement, useState } from 'react';
import { UserContext } from '@app/application/UserContext';

export const UserProvider = ({ children }: { children: ReactElement }) => {
  const [user, setUser] = useState({});

  console.log(user);
  return (
    <UserContext.Provider value={{ user, setUser }}>
      {children}
    </UserContext.Provider>
  );
};

The error that I received from this code

  1. There is no function that is calling the hook outside a functional component (there is?)!
  2. A important thing to note is that the UserProvider.tsx is part of a separate package for authentication that I'm building and importing from it with yarn link.
  3. I already tested to install directly from github without success.
  4. I already tested declaring the function with React.FC type but the result is the same.

The understanding that I have from it until now is that the react do not know that the App() function is a functional component and the call for UserProvider is inside a functional component.

I'm expecting that I can use hooks inside the provider, to work useState, useEffect, useNavigate.

Upvotes: 0

Views: 733

Answers (2)

Linda Paiste
Linda Paiste

Reputation: 42218

The error message that you posted contains three possible reasons for the error. Based on the information that you've provided, reason #3 seems like the most likely culprit.

  1. You might have mismatching versions of React and React DOM.
  2. You might be breaking the Rules of Hooks.
  3. You might have more than one copy of React in the same app.

I don't see anywhere in your code, at least not in what you've posted, that you are violating the rules of hooks.

It's what you've said here that jumps out:

A important thing to note is that the UserProvider.tsx is part of a separate package for authentication that I'm building and importing from it with yarn link.

I suspect that your reactjs-oauth2-pkce-provider package is declaring react in the dependencies rather than the peerDependencies. This would cause you to have two copies of react -- one from the package and another from your main app. If these two versions don't match, you could be dealing with reason #1 as well.

The "Duplicate React" section of the docs contains a few checks that you can do to confirm that you do in fact have two copies of React.

If you see more than one React, you’ll need to figure out why this happens and fix your dependency tree. For example, maybe a library you’re using incorrectly specifies react as a dependency (rather than a peer dependency).

Since this is a package that you created and control, you can fix the problem at its root. the solution is to remove react from the dependencies array in your package's package.json and move it to the peerDependencies array instead. You may also need it in the devDependencies. Here is a good example.

Upvotes: 0

Ahmedakhtar11
Ahmedakhtar11

Reputation: 1458

The error message is telling you that your error is in fact originating from your Hook call in UserProvider.tsx at line 5.

When you don't import components traditionally as react Components such as

<Component/> 

and instead import them as a function such as

return component();

or as in your case, importing them as a wrapper:

<Component>Parent</Component>

Then React hooks won't work.

I would recommend using Redux for logins or the useContext Hook to manage logins if you can't figure out the Traditional React Hooks way of managing this. useContext is also a React hook which would cause the same error if implemented in a similar way, but Redux wouldn't cause you to adhere to any of these strict React rules..

There's a lot of existing Login Templates on Github, including ones with Redux. Implementing Logins is the most boring and tedious process I've dealt with, which can usually take extremely long. Traditionally I use App Skeletons with login capabilities already implemented, and then add all the fun code over, but try the suggestions I mentioned.

Upvotes: 2

Related Questions