Reputation: 6796
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
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
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
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
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
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