3

im noob using react query and react with typesript, i don't know how to solve this: React Hook "useQuery" is called in function "onSubmit" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter.

export const LoginForm = () => { 

    const { handleSubmit, control } = useForm<IFormInput>({defaultValues: defaultValues, resolver: yupResolver(schema)});


    const onSubmit = ({email, password}: IFormInput) => {
        const {data, isLoading, error} = useQuery('loginUser', () => startLogin({email, password}));
        console.log(data);
        console.log(error);
    };

    ...
    ...
    ...
}

export const startLogin = ({email, password}: IFormInput) => (
    axios.post(loginEndpoint, {email, password}).then(res => res.data)
);
1
  • React component names must start with an uppercase letter I think you need to rename your component to uppercase first letter. Commented Aug 11, 2021 at 2:44

2 Answers 2

6

I’d like to add that for logging in a user, you probably don’t want a query but a mutation. Logging someone in is likely not a GET request and it has side effects (it makes the user be logged in), so useMutation is for that. You can define useMutation on the top of your functional component (in accordance with the rules of hooks) and invoke the returned mutate function in the callback:

export const LoginForm = () => { 
    const { mutate, isLoading } = useMutation(variables => startLogin(variables))
    
    const onSubmit = ({email, password}: IFormInput) => {
       mutate({ email, password })
    };
Sign up to request clarification or add additional context in comments.

Comments

2

First of all, the problem is just an eslint react plugin (rules-of-hooks) complaining about your use of a hooks.

You can tell it to shutup by adding the following comment above the line where the error is happening:

// eslint-disable-line react-hooks/rules-of-hooks

However...

this is only going to prevent you from understanding the correct way of using hooks in react. Before you proceed with the above, this is the correct way to handle your use case.

First move the hook outside of the function, and instead of useQuery, use useMutation:

export const LoginForm = () => { 

    const { handleSubmit, control } = useForm<IFormInput>({defaultValues: defaultValues, resolver: yupResolver(schema)});
    const { data, error, mutate: loginUser } = useMutation(startLogin);


    const onSubmit = ({email, password}: IFormInput) => {
        loginUser({email, password});
        console.log(data);
        console.log(error);
    };
}

Now that that's done, as I mentioned before, reason you got the complaint from eslint is because the rules-of-hooks plugin has plain no nonsense rule that assumes any function starting with use* must be a react hook. It also assumes that such a function is only used inside a react component hence the part of the message that says:

React component names must start with an uppercase letter.

The reason this rule exists is explained here. Essentially it comes down to the following:

  • rules-of-hooks assumes that any custom react hook will make use of one of the existing react hooks (useEffect, useState, useMemo, etc...), and since these hooks affect the state of the component, it is assumed that your custom hook does soo to (even though you may not have written the useQuery hook).
  • React functional components rely on order of hooks to maintain state. If that order is broken at any point during the render of the component, the component is unable to maintain its internal state.

Therefore, specify all potential mutations at the top of your components.

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.