Shobhit Tewari
Shobhit Tewari

Reputation: 535

[Unhandled promise rejection: Error: Invalid hook call. Hooks can only be called inside of the body of a function component

Hello I am making a react native app. This is my first react-native project and second project using react. Anyway I am getting this error in my react native project. I am posting my modules please help me.

So this is my module which uploads the profile picture to my express server.

const updateProfilePicture = image => {
    try {
        console.log("Update profile picture hit");
        const { user: token } = useAuth();
        console.log(`Token received: ${token}`);
        const data = new FormData();

        console.log(image);
        
        let fileName = image.split("/");
        fileName = fileName[fileName.length-1]
        console.log(`File name: ${fileName}`)
        let extensionName = fileName.split(".");
        extensionName = extensionName[extensionName.length-1];
        console.log(`Extension name: ${extensionName}`)

        data.append('token', token);

        data.append('pimage', {
            name: Random.getRandomBytes(8).toString('hex')+"."+extensionName,
            type: 'image/'+extensionName,
            uri: image
        });

        console.log(`This is the data\n`+data);

        return authClient.post(endpointUpdatePicture, data);
    } catch(error) {
        console.log("Error in update profile picture", error);
    }
};

From hit and try I found that the line const { user: token } = useAuth(); is making it wrong.

Before going forward, useAuth() is my custom hook for tracking down user. user is actually a jwt token.

Here is my useAuth()

import { useContext } from 'react';

import authStorage from './storage';
import AuthContext from './context';

import jwt from 'jwt-decode';

export default useAuth = () => {

    const {user, setUser} = useContext(AuthContext);

    const { name, rating, number, uri } = jwt(user);

    const logout = () => {
        setUser(null);
        authStorage.removeToken();
    }

    console.log(`Uri: ${uri}`);

    return { user, setUser, logout, name, rating, number, uri };
}

Now I have created a context in my App.js from where I get this user and setUser basically the token. Writing this line is throwing me the hook error.

Please help me in 2 ways:

  1. Please tell me why this error occurs because as you see I have not violated any hook law as I can see.
  2. Please tell me if I am doing it right.

Upvotes: 1

Views: 907

Answers (3)

Akif Hadziabdic
Akif Hadziabdic

Reputation: 2890

Hooks in react functional components have to be used in the main component function or as a part of custom hooks, without conditions, loops, or callbacks. You have to move useAuth hook to the main component function, outside try-catch block, and outside updateProfilePicture function.

Upvotes: 1

buzatto
buzatto

Reputation: 10382

since your updateProfilePicture is not called at your component body, you should change it to receive as param your token.

Then at your Component you can call your hook useAuth at component body, extracting the desired token. This way you can pass it as variable to updateProfilePicture without facing any error, since useAuth will be called correctly at your function body.

your code would look something like:

const updateProfilePicture = (image, token) => {
  // ... same code here without 'useAuth'
}

const Component = ({ image }) => {
  const { user: token } = useAuth();

  const onsubmit = () => updateProfilePicture(img, token)

  return (
    <>
      <div>upload here image</div>
      <button onClick={() => onsubmit(image, token)}>upload</button>
    </>
  )
}

Upvotes: 2

Shivam Jha
Shivam Jha

Reputation: 4482

According to React Documentation

Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function, before any early returns. By following this rule, you ensure that Hooks are called in the same order each time a component renders. That’s what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls.

✅ Call Hooks from React function components.

✅ Call Hooks from custom Hooks (we’ll learn about them on the next page).

Your useAuth hook is called inside try-catch block. Instead, call it at top-level of the functional component

Upvotes: 0

Related Questions