Marco Jr
Marco Jr

Reputation: 6796

how to use useMutation or useQuery as hook on React or React Native?

That's the exception that I got..and it's does not make sense for me...

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 See fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.

this is my component...I am trying to archive just an standard login/password screen...

import React from 'react'
import { View, Text, TouchableWithoutFeedback, TextInput } from 'react- 
native'
import style from './style'
import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome'
import { faUser, faUnlockAlt } from '@fortawesome/free-solid-svg-icons'
import { Query, useMutation } from 'react-apollo'
import { testQuery, LOGIN_MUTATION } from '../../gql/session'

class LoginForm extends React.Component {
constructor(props) {
    super(props)
    this.state = {
        inProgress: false,
        email: '[email protected]',
        password: '1234'
    }
}
doLogin() {
    const [_doLogin ] = useMutation(LOGIN_MUTATION, {
        update: (proxy, mutationResult) => {
            console.log(mutationResult)
        }
    ,
    variables: {
      $email: this.setState.email,
      $password: this.state.password
    }
    })
     _doLogin()
}
render() {
    return (
        <View style={style.form}>
            <Text style={style.formLabel}>E-Mail</Text>
            <View style={style.formRow}>
                <FontAwesomeIcon size={28} style={style.formIcon} icon={faUser} />
                <TextInput
                    onChangeText={(email) => this.setState({ email })}
                    value={this.state.email}
                    keyboardType={'email-address'}
                    style={style.textInput} />
            </View>
            <Text style={style.formLabel}>Password</Text>
            <View style={style.formRow}>
                <FontAwesomeIcon size={28} style={style.formIcon} icon={faUnlockAlt} />
                <TextInput
                    onChangeText={(password) => this.setState({ password })}
                    value={this.state.password}
                    secureTextEntry={true}
                    style={style.textInput} />
            </View>

            <TouchableWithoutFeedback onPress={() => { this.doLogin() }}>
                <View style={[style.button, style.doLoginButton]}>
                    <Text style={style.buttonText}>Login</Text>
                </View>
            </TouchableWithoutFeedback>
            <View style={style.bellowButton}>
                <TouchableWithoutFeedback onPress={() => this.props.onCancel()}>
                    <Text style={style.cancel}>Cancel</Text>
                </TouchableWithoutFeedback>
                <TouchableWithoutFeedback onPress={() => this.props.onForgot()}>
                    <Text style={style.forgot}>Forgot ?</Text>
                </TouchableWithoutFeedback>
            </View>
        </View>
    )
   }
}


export default LoginForm

So, what's wrong ? and how to archive it ?

Upvotes: 4

Views: 14997

Answers (5)

Rashid
Rashid

Reputation: 375

Adding a comment so people could find the solution.

The main difference is the flow of data, useQuery is used to query async data, and useMutation is used for CRUD operation.

Examples: https://thesyntaxdiaries.com/what-is-react-query-how-to-use-usemutation-usequery-prefetch-devtools/

Upvotes: 0

Mohammed Al-Reai
Mohammed Al-Reai

Reputation: 2796

try this don froget instll package @apollo/react-hooks

import React from 'react'
import {View, Text, TouchableWithoutFeedback, TextInput} from 'react-
 native '
 import {useMutation} from '@apollo/react-hooks';

import style from './style'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {faUser, faUnlockAlt} from '@fortawesome/free-solid-svg-icons'
import {testQuery, LOGIN_MUTATION} from '../../gql/session'

class LoginForm extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            inProgress: false,
            email: '[email protected]',
            password: '1234'
        }
    }

    render() {
        const [addTodo] = useMutation(ADD_TODO);

        return (
            <View style={style.form}>
                <Text style={style.formLabel}>E-Mail</Text>
                <View style={style.formRow}>
                    <FontAwesomeIcon size={28} style={style.formIcon} icon={faUser}/>
                    <TextInput
                        onChangeText={(email) => this.setState({email})}
                        value={this.state.email}
                        keyboardType={'email-address'}
                        style={style.textInput}/>
                </View>
                <Text style={style.formLabel}>Password</Text>
                <View style={style.formRow}>
                    <FontAwesomeIcon size={28} style={style.formIcon} icon={faUnlockAlt}/>
                    <TextInput
                        onChangeText={(password) => this.setState({password})}
                        value={this.state.password}
                        secureTextEntry={true}
                        style={style.textInput}/>
                </View>

                <TouchableWithoutFeedback
                    onPress={() => {
                      ADD_TODO({
                        variables: {
                            email: this.setState.email,
                            password: this.state.password
                        },
                        update: (proxy, mutationResult) => {
                            console.log(mutationResult)
                        }})}}>


                    <View
                    style={[style.button, style.doLoginButton]}>
                    <Text style={style.buttonText}>Login</Text>
                </View>
            </TouchableWithoutFeedback>
            <View style={style.bellowButton}>
                <TouchableWithoutFeedback onPress={() => this.props.onCancel()}>
                    <Text style={style.cancel}>Cancel</Text>
                </TouchableWithoutFeedback>
                <TouchableWithoutFeedback onPress={() => this.props.onForgot()}>
                    <Text style={style.forgot}>Forgot ?</Text>
                </TouchableWithoutFeedback>
            </View>
        </View>
        ) } }

Upvotes: -1

Guruprasad
Guruprasad

Reputation: 783

The error you are getting is because you are trying to use hooks in class components, so in the docs they have mentioned the following:

You can’t use Hooks inside of a class component, but you can definitely mix classes and function components with Hooks in a single tree. Whether a component is a class or a function that uses Hooks is an implementation detail of that component. In the longer term, we expect Hooks to be the primary way people write React components.

Upvotes: 7

Patrik Prevuznak
Patrik Prevuznak

Reputation: 2261

From the fb.me/react-invalid-hook-call link that error gave you:

Hooks can only be called inside the body of a function component.

You have a class component, you need to convert it to functional component in order to use react hooks.

Or if you're used to class components, use Mutation component from '@apollo/react-components'.

See more on this link: https://www.apollographql.com/docs/react/api/react-components/

Upvotes: 1

hwkd
hwkd

Reputation: 2648

I'd like to point out that you're currently using a class component but hooks were designed to be used with a functional component. So once you change your component to a functional component, you can then follow the example on the official docs for apollo graphql hooks as shown below, and then try it out for your use case.

import gql from 'graphql-tag';
import { useMutation } from '@apollo/react-hooks';

const ADD_TODO = gql`
  mutation AddTodo($type: String!) {
    addTodo(type: $type) {
      id
      type
    }
  }
`;

function AddTodo() {
  let input;
  const [addTodo] = useMutation(ADD_TODO);

  return (
    <div>
      <form
        onSubmit={e => {
          e.preventDefault();
          addTodo({ variables: { type: input.value } });
          input.value = '';
        }}
      >
        <input
          ref={node => {
            input = node;
          }}
        />
        <button type="submit">Add Todo</button>
      </form>
    </div>
  );
}

export default AddTodo();

source: https://www.apollographql.com/docs/react/essentials/mutations/

Upvotes: 0

Related Questions