2

Getting below error:

Unhandled Rejection (Error): Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as 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

My Sign In Form

export const SignInView: FC<{ path: string }> = (): ReactElement => {
  type Inputs = {
    userId: string;
  };

 function fetchUser(id: string): UseQueryResult {
  return useQuery('fetchUser', async () => {
    const response: Response = await fetch("http://localhost:8080/users/" + id, RequestInit = {method: 'GET'});
    return response;
  });
}

  const { register, handleSubmit, getValues, errors, setError } = useForm<Inputs>();

  const onSubmit = (): void => {
    const { userId } = getValues();
    //throws Invalid hook call. Hooks can only be called inside of the body of a function component
    const { data } = fetchUser(userId);
   //....some logic here.
}

return (
    <div className='container container-rounded border w-25 bg-white text-center'>
      <div className='row p-2 mt-2 text-center'>
        <div className='col'>
          <p className='h3' data-content='header'>
            Demo
          </p>
        </div>
      </div>

      <div className='row p-2'>
        <div className='col'>
          <h5>Sign in</h5>
        </div>
      </div>

      <Form onSubmit={handleSubmit(onSubmit)}>
        <div className='row'>
          <div className='col form-group'>
            <Form.Control
              type='text'
              name='userId'
              autoFocus
              ref={register({ required: true })}
              className='form-control form-control-lg'
              placeholder='User ID'
              data-field='userId'
            />
          </div>
        </div>

        <div className='row p-2'>
          <div className='col text-center'>
            <Button
              type='submit'
              className='default btn btn-primary btn-lg btn-block button-rounded'
              data-action='sign-in'>
              Sign in
            </Button>
          </div>
        </div>
      </Form>
)

I have seen suggestions that say useMutation instead and invoke mutate callback function but this is a GET call, so useQuery is more appropriate in this case.

1 Answer 1

3

The error is correct as you are trying to call the hook not inside the body of the <SignInView /> component.

As you are returning a useQuery hook from your fetchUser function it's also a react convention to use the "use" prefix for your custom hook, so you can call it just useUser.

You can get your use case to work by invoking the call to your api manually. Just set the query's enabled config option to false and trigger the fetch by using refetch in your onSubmit callback.

Then use RHF's watch to pass the current value of your <Form.Control /> to your useUser hook.

function useUser(id: string): UseQueryResult {
  return useQuery('fetchUser', async () => {
    const response: Response = await fetch("http://localhost:8080/users/" + id, RequestInit = {method: 'GET'});
    return response;
  }, { enabled: false });
}
export const SignInView: FC<{ path: string }> = (): ReactElement => {
 const { register, handleSubmit, errors, setError, watch } = useForm<Inputs>();
 const userId = watch('userId');
 const { refetch } = useUser(userId);

 const onSubmit = async (): void => {
  const { data } = await refetch();
  //....some logic here.
 }

return (...);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.