Search code examples
javascriptfirebasereact-nativeruntime-errorhook

Invalid Hook Call React Native


I keep on getting this error on my register screen. I would really appreciate it if you could let me know what the issue is. Thank you!

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 See https: //fb me/react-invalid-hook-call for tips about how to debug and fix this problem.
import { ImageBackground, StyleSheet, StatusBar, Dimensions, View, Image } from 'react-native';
import { Block, Button, Text, theme } from 'galio-framework';
import * as Yup from 'yup';
import SafeView from '../components/SafeView';
import Form from '../components/Forms/Form';
import FormField from '../components/Forms/FormField';
import FormButton from '../components/Forms/FormButton';
import IconButton from '../components/IconButton';
import FormErrorMessage from '../components/Forms/FormErrorMessage';
import { registerWithEmail } from '../config/firebase';

const { height, width } = Dimensions.get('screen');
const validationSchema = Yup.object().shape({
  name: Yup.string()
    .required()
    .label('Name'),
  email: Yup.string()
    .required('Please enter a valid email')
    .email()
    .label('Email'),
  password: Yup.string()
    .required()
    .min(6, 'Password must have at least 6 characters')
    .label('Password'),
  confirmPassword: Yup.string()
    .oneOf([Yup.ref('password')], 'Confirm Password must match Password')
    .required('Confirm Password is required')
});
const [passwordVisibility, setPasswordVisibility] = useState(true);
const [rightIcon, setRightIcon] = useState('eye');
const [confirmPasswordIcon, setConfirmPasswordIcon] = useState('eye');
const [confirmPasswordVisibility, setConfirmPasswordVisibility] = useState(true);
const [registerError, setRegisterError] = useState('');

function handlePasswordVisibility() {
  if (rightIcon === 'eye') {
    setRightIcon('eye-off');
    setPasswordVisibility(!passwordVisibility);
  } else if (rightIcon === 'eye-off') {
    setRightIcon('eye');
    setPasswordVisibility(!passwordVisibility);
  }
}

function handleConfirmPasswordVisibility() {
  if (confirmPasswordIcon === 'eye') {
    setConfirmPasswordIcon('eye-off');
    setConfirmPasswordVisibility(!confirmPasswordVisibility);
  } else if (confirmPasswordIcon === 'eye-off') {
    setConfirmPasswordIcon('eye');
    setConfirmPasswordVisibility(!confirmPasswordVisibility);
  }
}

async function handleOnSignUp(values, actions) {
  const { email, password } = values;
  try {
    await registerWithEmail(email, password);
  } catch (error) {
    setRegisterError(error.message);
  }
}

export default class Register extends React.Component {
  render() {
    const { navigation } = this.props;
    return (
      <SafeView style={styles.container}>
        <Form
          initialValues={{
            name: '',
            email: '',
            password: '',
            confirmPassword: ''
          }}
          validationSchema={validationSchema}
          onSubmit={values => handleOnSignUp(values)}
        >
          <FormField
            name="name"
            leftIcon="account"
            placeholder="Enter name"
            autoFocus={true}
          />
          <FormField
            name="email"
            leftIcon="email"
            placeholder="Enter email"
            autoCapitalize="none"
            keyboardType="email-address"
            textContentType="emailAddress"
          />
          <FormField
            name="password"
            leftIcon="lock"
            placeholder="Enter password"
            autoCapitalize="none"
            autoCorrect={false}
            secureTextEntry={passwordVisibility}
            textContentType="password"
            rightIcon={rightIcon}
            handlePasswordVisibility={handlePasswordVisibility}
          />
          <FormField
            name="confirmPassword"
            leftIcon="lock"
            placeholder="Confirm password"
            autoCapitalize="none"
            autoCorrect={false}
            secureTextEntry={confirmPasswordVisibility}
            textContentType="password"
            rightIcon={confirmPasswordIcon}
            handlePasswordVisibility={handleConfirmPasswordVisibility}
          />
          <FormButton title={'Register'} />
          {<FormErrorMessage error={registerError} visible={true} />}
        </Form>
        <IconButton
          style={styles.backButton}
          iconName="keyboard-backspace"
          color={Colors.white}
          size={30}
          onPress={() => navigation.goBack()}
        />
      </SafeView>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    padding: 15,
  },
  backButton: {
    justifyContent: 'center',
    alignItems: 'center',
    marginVertical: 10
  }
});```

Solution

  • As the error suggests, you are not using hooks correctly. Hooks need to be inside of a functional component. Currently, you are using them without a component. The only component you have here is a class component, so if you want to use hooks, you need to first convert it to a functional component, something like this:

    import React, { useState } from 'react';
    
    const Register = (props) => {
    
      const [passwordVisibility, setPasswordVisibility] = useState(true);
      const [rightIcon, setRightIcon] = useState('eye');
      const [confirmPasswordIcon, setConfirmPasswordIcon] = useState('eye');
      const [confirmPasswordVisibility, setConfirmPasswordVisibility] = useState(true);
      const [registerError, setRegisterError] = useState('');
    
      // other component logic code here
    
      return (
        // your component rendering code here
      );
    }
    
    export default Register;