'React Native Error: Element type is invalid (Formik)
I have a problem with Login Screen I am using Formik to use custom TextInputs but I am getting this error: (Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.)
This is my LoginScreen.js
import React, {useState} from 'react';
import { Alert,
Image,
KeyboardAvoidingView,
ScrollView,
StyleSheet,
TouchableOpacity,
View,
} from 'react-native';
import AppText from '../../components/AppText';
import AppButton from '../../components/AppButton';
import colors from '../../configs/colors';
import AppInput from '../../components/AppInput';
import {Formik} from 'formik';
import * as Yup from 'yup';
import http from '../../services/http';
import storage from '../../services/storage';
import {setUser} from '../../store/reducers/auth';
import {CommonActions} from '@react-navigation/native';
import {useDispatch} from 'react-redux';
import ProgressDialog from 'react-native-progress-dialog';
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
const LoginScreen = ({navigation}) => {
const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const loginUser = async values => {
try {
setLoading(true);
values['role'] = 2;
values['device_token'] ='XYZ';
const res = await http.post({
url: '/user/login',
body: values,
});
console.log('Res => ', res.data);
if (res.data.records.isVerified === 1) {
dispatch(setUser(res.data));
http.setUserTokenAndId(
res.data.records.accessToken,
res.data.records.id,
);
await storage.store('USER', res.data);
navigation.dispatch(
CommonActions.reset({
index: 0,
routes: [{name: 'Home'}],
}),
);
} else {
Alert.alert('Error', res.data.message, [
{
text: 'Resend Email',
onPress: () => {
resendEmail(res.data.records.accessToken);
},
style: 'destructive',
},
{
text: 'Cancel',
onPress: () => {},
style: 'cancel',
},
]);
}
} catch (err) {
console.log('Err => ', err);
} finally {
setLoading(false);
}
};
const resendEmail = async token => {
try {
setLoading(true);
const res = await http.post({
url: '/email/verification-notification',
body: {},
headers: {Authorization: 'Bearer ' + token},
});
Alert.alert('Success', res.data.message);
} catch (err) {
console.log('Err', err);
} finally {
setLoading(false);
}
};
return (
<View style={styles.container}>
<View style={styles.cardContainer}>
<View style={styles.card}>
<View>
<KeyboardAwareScrollView style={{height: '100%'}}>
<>
<Image source={require('../../assets/header.png')} />
<AppText style={styles.headingText}>Sign In To Forsa</AppText>
<AppText style={styles.subHeadingText}>
Welcome Back! sign in to your previous account to continue the
shoping
</AppText>
</>
<View>
<Formik
initialValues={{email: '', password: ''}}
validationSchema={Yup.object({
email: Yup.string().label('Email').required(),
password: Yup.string().label('Password').min(5).required(),
})}
onSubmit={loginUser}>
{({submitForm}) => {
return (
<View>
<Image
style={{
alignItems: 'center',
marginTop: 10,
height: 150,
width: '100%',
}}
resizeMode="contain"
source={require('../../assets/loginicon.png')}
/>
<View style={{marginHorizontal: 20}}>
<AppInput
label=""
placeholder="Email*"
keyboardType="email-address"
name="email"
iconName="email"
autoComplete={true}
inputStyle={styles.input}
inputWrapperStyle={styles.inputWrapper}
/>
<AppInput
label=""
placeholder="Password*"
name="password"
secureTextEntry={true}
iconName="lock"
inputWrapperStyle={styles.inputWrapper}
inputStyle={styles.input}
/>
</View>
<AppButton
containerStyle={styles.loginBtn}
onPress={submitForm}
title={'Login'}></AppButton>
<View
style={{
justifyContent: 'space-between',
flexDirection: 'row',
marginTop: 10,
}}>
<View />
<AppText
style={{
color: colors.TAB_BAR_GREY,
fontSize: 13,
marginRight: 25,
}}
onPress={() =>
navigation.navigate('forgotPassword')
}>
Forgot Password?
</AppText>
</View>
<View
style={{
justifyContent: 'center',
flexDirection: 'row',
marginTop: 10,
}}>
<AppText>Don't have any account yet?</AppText>
<TouchableOpacity
onPress={() =>
navigation.navigate('CreateAccount')
}>
<AppText
style={{
marginLeft: 10,
color: colors.PRIMARY_GREEN,
}}>
Sign Up
</AppText>
</TouchableOpacity>
</View>
</View>
);
}}
</Formik>
</View>
</KeyboardAwareScrollView>
</View>
{loading && (
<ProgressDialog
loaderColor={colors.PRIMARY_GREEN}
visible={loading}
labelStyle={{marginTop: 10}}
/>
)}
</View>
</View>
</View>
);
};
export default LoginScreen;
const styles = StyleSheet.create({
headingText: {
fontSize: 30,
position: 'absolute',
marginTop: 80,
marginLeft: 20,
color: colors.WHITE,
fontWeight: '600',
},
subHeadingText: {
fontSize: 18,
position: 'absolute',
marginTop: 120,
marginLeft: 20,
color: colors.WHITE,
fontWeight: '400',
},
loginBtn: {
marginTop: 20,
borderRadius: 50,
marginHorizontal: 20,
},
input: {
paddingLeft: 10,
},
inputWrapper: {
borderWidth: 0.5,
borderRadius: 50,
},
label: {
color: colors.PRIMARY_GREEN,
},
loading: {
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
alignItems: 'center',
justifyContent: 'center',
// backgroundColor: "rgba(66,66,66,0.47)",
},
btnText: {
color: colors.WHITE,
fontSize: 16,
},
});
This is my AppInput.js (Which is custom TextInput):
import React from 'react';
import {View, TextInput, StyleSheet, Platform} from 'react-native';
import AppText from './AppText';
import {useFormikContext} from 'formik';
import colors from '../configs/colors';
import {MaterialCommunityIcons} from 'react-native-vector-
icons/MaterialCommunityIcons';
export default props => {
const {
name,
label,
labelStyle,
inputWrapperStyle,
inputWrapperErrorStyle,
inputStyle,
errorStyle,
containerStyle,
iconName,
value,
multiline = false,
editable = true,
} = props;
const {values, errors, touched, setFieldValue} = useFormikContext();
let wrapperErrorStyle = error
? {
borderWidth: 1,
borderColor: colors.ERROR_TEXT,
...inputWrapperErrorStyle,
}
: {
// borderWidth: 1,
// borderColor: props.value ? colors.LIGHT_GREY : colors.LIGHT_GREY,
...inputWrapperErrorStyle,
};
const error = touched[name] && errors[name];
let iconColor = props.value ? colors.PRIMARY_GREEN : colors.TAB_BAR_GREY;
if (error) iconColor = colors.errorText;
return (
<View style={[styles.containerStyle, containerStyle]}>
<AppText style={[styles.label, labelStyle]}>{label}</AppText>
<View style={[styles.inputWrapper, inputWrapperStyle, wrapperErrorStyle]}>
{iconName && (
<MaterialCommunityIcons
name={iconName}
size={25}
style={styles.iconStyles}
color={iconColor}
/>
)}
<TextInput
{...props}
value={value}
editable={editable}
onChangeText={txt => {
setFieldValue(name, txt);
}}
multiline={multiline}
placeholderTextColor={colors.TAB_BAR_GREY}
style={[styles.input, inputStyle]}
/>
</View>
{error ? (
<AppText style={[styles.error, errorStyle]}>{error}</AppText>
) : null}
</View>
);
};
const styles = StyleSheet.create({
containerStyle: {
marginTop: Platform.OS === 'ios' ? 5 : 0,
marginBottom: 0,
},
label: {
fontSize: 15,
},
inputWrapper: {
flexDirection: 'row',
borderWidth: 0,
},
iconStyles: {
justifyContent: 'center',
alignItems: 'center',
marginTop: 7,
marginLeft: 18,
},
input: {
flex: 1,
minHeight: 40,
maxHeight: 150,
fontSize: 16,
color: colors.BLACK,
},
error: {
color: colors.ERROR_TEXT,
marginTop: 3,
fontSize: 16,
},
});
I am searching from 3-4 hours but couldn't find any solution to this, I am kinda new to react native. Any help will be appreciated. Thank you.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
