Loading Component in React native with Firebase and redux - reactjs

Click here to View Page
I need your help here. I want to add Activity indicator with timeout after Login button is pressed but login button is already configured to loginUser() function! I just need to show activity indicator for some secs and login the user when button is pressed! Thankyou I been trying for week. I'm helpless. So please help me!
import React, { Component } from 'react';
import { StyleSheet, View, Text, Alert, TouchableOpacity, ActivityIndicator } from 'react-native';
import { Form, Input, Item, Button, Label, Body, } from 'native-base';
import { login } from "../actions";
import { Actions } from "react-native-router-flux";
import { connect } from "react-redux";
import { colors } from "../../../colors";
class UserLoginForm extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: '',
};
this.loginUser = this.loginUser.bind(this);
this.loginSuccessCallback = this.loginSuccessCallback.bind(this);
this.loginErrorCallback = this.loginErrorCallback.bind(this);
}
forgotPassword() {
Actions.ForgotPassword();
};
loginSuccessCallback(user) {
};
loginErrorCallback(error) {
switch (error.code) {
case 'auth/user-not-found':
Alert.alert('Error', 'User not found. New user? SignUp');
break;
case 'auth/wrong-password':
Alert.alert('Error', 'Wrong Password');
break;
}
};
loginUser() {
const { email, password } = this.state;
const data = { email, password };
this.props.dispatch(login(data, this.loginSuccessCallback, this.loginErrorCallback));
};
render() {
return (
<View style={styles.container}>
<Form>
<Item floatingLabel>
<Label>Email</Label>
<Input
autoCorrect={false}
autoCapitalize="none"
returnKeyType="done"
onChangeText={(email) => this.setState({ email })} />
</Item>
<Item floatingLabel>
<Label>Password</Label>
<Input
secureTextEntry={true}
autoCorrect={false}
autoCapitalize="none"
returnKeyType="go"
onSubmitEditing={this.loginUser}
onChangeText={(password) => this.setState({ password })} />
</Item>
<Button style={styles.loginButton}
full
rounded
onPress={this.loginUser}>
<Text style={{ fontWeight: 'bold', color: 'white', fontSize: 20 }}>Login</Text>
</Button>
<TouchableOpacity onPress={this.forgotPassword}>
<Text style={styles.forgotButton}>Forgot Password?</Text>
</TouchableOpacity>
<--------------Loading Component ------------------>
<View style={styles.loading}>
<ActivityIndicator
animating={this.state.animating}
style={[{ height: 80 }]}
color="#C00"
size="large"
hidesWhenStopped={true} />
<Text style={{ color: 'red' }}>loading..</Text>
</View>
<------------------------------------------------------------------->
</Form>
</View>
);
}
}
function mapStateToProps(state, props) {
return {
user: state.authReducer.user,
};
}
export default connect(
mapStateToProps,
null
)(UserLoginForm);
const styles = StyleSheet.create({
container: {
marginTop: 10
},
loginButton: {
alignSelf: 'center',
marginTop: 10,
width: 250
},
forgotButton: {
alignSelf: 'center',
marginTop: 15,
color: colors.white
},
loading: {
position: 'absolute',
opacity: 0.5,
height: '50%',
width: '35%',
backgroundColor: 'black',
alignSelf: 'center',
alignItems: 'center',
borderBottomLeftRadius: 20,
borderBottomRightRadius: 20,
borderTopRightRadius: 20,
borderTopLeftRadius: 20,
}
})
Login function goes here..
<--------------------------------------------------------------------------------------------------->
import * as t from "./actionTypes";
import {auth} from "../../config/firebase";
import * as api from "./api";
export function register(data, successCB, errorCB) {
return dispatch => {
api.register(data, function (success, data, error) {
if (success) {
successCB(data);
} else if (error) errorCB(error);
});
};
}
export function checkLoginStatus(callback) {
return dispatch => {
auth.onAuthStateChanged(authUser => {
let isLoggedIn = authUser !== null;
if (isLoggedIn) {
api.getUser(authUser, function (success, {exists, user}, error) {
if (success) {
if (exists) {
dispatch({type: t.USER_LOGGED_IN, data: user});
callback(true, 'user');
}
else {
api.getEmployee(authUser, function (success, {exists, user}, error) {
if (success && exists) {
dispatch({type: t.EMPLOYEE_LOGGED_IN, data: user});
callback(true, 'employee');
} else {
dispatch({type: t.LOGGED_OUT});
callback(false);
}
})
}
} else if (error) {
//unable to get user
dispatch({type: t.LOGGED_OUT});
callback(false);
}
});
} else {
dispatch({type: t.LOGGED_OUT});
callback(false);
}
});
};
}
export function login(data, successCB, errorCB) {
return dispatch => {
api.login(data, function (success, data, error) {
if (success) {
if (data.exists) dispatch({type: t.USER_LOGGED_IN, data: data.user});
successCB(data);
} else if (error) errorCB(error);
});
};
}
export function logout(errorCB) {
return dispatch => {
api.logout(function (success, data, error) {
if (success) {
dispatch({type: t.LOGGED_OUT});
} else if (error) errorCB(error);
});
};
}
export function loginEmployee(data, successCB, errorCB) {
return dispatch => {
api.loginEmployee(data, function (success, data, error) {
if (success) {
if (data.exists) dispatch({type: t.EMPLOYEE_LOGGED_IN, data: data.user});
successCB(data);
} else if (error) errorCB(error);
});
};
}

Related

React native, axios put request

The first problem: when opening a modal with editing an avatar, 2 requests are sent to the server.
The second problem: the avatar is not updated. The answer comes that the email should be specified, but I just pass the string. The full text of the error is shown in the screenshot.
Sending an avatar change request
import { BottomSheet } from '#rneui/themed'
import { FC, useState } from 'react'
import { useForm } from 'react-hook-form'
import { Pressable, ScrollView, View } from 'react-native'
import GestureRecognizer from 'react-native-swipe-gestures'
import { IUser } from '#/types/user.inteerface'
import { IAvatarEdit } from '#/components/screens/profile/avatarEdit/avatarEdit.interface'
import { useAvatar } from '#/components/screens/profile/avatarEdit/useAvatar'
import { Avatars, Button, Heading, Layout } from '#/components/ui'
import { getModalStyle, modalStyle } from '#/components/ui/style'
type AvatarData = {
image_url: string
}
const dataList: AvatarData[] = [
{
image_url:
'https://cdn.pixabay.com/photo/2017/03/01/22/18/avatar-2109804_1280.png'
},
{
image_url: 'https://randomuser.me/api/portraits/men/36.jpg'
},
{
image_url:
'https://cdn.pixabay.com/photo/2019/11/03/20/11/portrait-4599553__340.jpg'
},
{
image_url:
'https://cdn.pixabay.com/photo/2014/09/17/20/03/profile-449912__340.jpg'
},
{
image_url:
'https://cdn.pixabay.com/photo/2020/09/18/05/58/lights-5580916__340.jpg'
},
{
image_url:
'https://cdn.pixabay.com/photo/2016/11/21/12/42/beard-1845166_1280.jpg'
},
{
image_url:
'https://cdn.pixabay.com/photo/2012/04/18/18/07/user-37448_1280.png'
},
{
image_url: 'https://randomuser.me/api/portraits/men/36.jpg'
},
{
image_url:
'https://cdn.pixabay.com/photo/2019/11/03/20/11/portrait-4599553__340.jpg'
},
{
image_url:
'https://cdn.pixabay.com/photo/2014/09/17/20/03/profile-449912__340.jpg'
},
{
image_url:
'https://cdn.pixabay.com/photo/2020/09/18/05/58/lights-5580916__340.jpg'
},
{
image_url:
'https://cdn.pixabay.com/photo/2016/11/21/12/42/beard-1845166_1280.jpg'
}
]
const AvatarEdit: FC<IAvatarEdit> = ({ onClose, isVisible, ...props }) => {
const { setValue } = useForm<IUser>()
const { onSubmit, user } = useAvatar(setValue)
const [selected, setSelected] = useState<string>(user?.avatar || '')
const onAvatarSubmit = () => {
onSubmit({ avatar: selected } as IUser)
onClose()
}
return (
<GestureRecognizer
onSwipeDown={onClose}
config={{
velocityThreshold: 0.3,
directionalOffsetThreshold: 80
}}
style={{
flex: 1
}}
>
<BottomSheet
backdropStyle={{
backgroundColor: 'rgba(0, 0, 0, 0.5)'
}}
onBackdropPress={onClose}
isVisible={isVisible}
{...props}
>
<Layout
style={{
...getModalStyle(modalStyle)
}}
>
<View
style={{
flex: 1,
paddingHorizontal: 20,
paddingVertical: 20
}}
>
<Heading className='pb-3' title='Edit' />
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'flex-start'
}}
>
<Avatars
rounded={true}
size={100}
source={selected ? { uri: selected } : { uri: user?.avatar }}
/>
<View
style={{
marginTop: 15,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-end'
}}
>
<Button style={{ marginRight: 10 }} onPress={onAvatarSubmit}>
Save
</Button>
</View>
</View>
</View>
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
style={{ flex: 1 }}
>
{dataList.map((item, index) => (
<Pressable key={index}>
<Avatars
onPress={() => setSelected(item.image_url)}
rounded={true}
key={index}
size={60}
source={{ uri: item.image_url }}
/>
</Pressable>
))}
</ScrollView>
</Layout>
</BottomSheet>
</GestureRecognizer>
)
}
export default AvatarEdit
import { IAuthFormData } from '#/types/auth.interface'
import { IUser } from '#/types/user.inteerface'
import { getUserUrl } from '#/config/api.config'
import { request } from '#/services/api/request.api'
export const UserService = {
async getAll(searchTerm?: string) {
return request<IUser[]>({
url: getUserUrl(''),
method: 'GET',
params: searchTerm ? { searchTerm } : {}
})
},
async getProfile() {
return request<IUser>({
url: getUserUrl('profile'),
method: 'GET'
})
},
async getById(_id: string) {
return request<IUser>({
url: getUserUrl(`${_id}`),
method: 'GET'
})
},
async updateProfile(data: IAuthFormData) {
return request<IUser>({
url: getUserUrl('profile'),
method: 'PUT',
data
})
},
async updateUser(data: IAuthFormData, _id: string) {
return request<string>({
url: getUserUrl('profile'),
method: 'PUT',
data
})
},
async updateAvatar(data: IUser) {
return request<string>({
url: getUserUrl('profile'),
method: 'PUT',
data
})
},
async deleteUser(_id: string) {
return request<string>({
url: getUserUrl(`${_id}`),
method: 'DELETE'
})
}
// async getFavorites() {
// return request<IUser>({
// url: getUserUrl('profile/favorites'),
// method: 'GET'
// })
// },
}
import { useMutation, useQuery } from '#tanstack/react-query'
import { SubmitHandler, UseFormSetValue } from 'react-hook-form'
import Toast from 'react-native-toast-message'
import { IUser } from '#/types/user.inteerface'
import { UserService } from '#/services/user/user.service'
export const useAvatar = (setValue: UseFormSetValue<IUser>) => {
const { isLoading, data: user } = useQuery(
['avatar'],
() => UserService.getProfile(),
{
onSuccess: ({ avatar }) => {
setValue('avatar', avatar)
}
}
)
const { mutateAsync } = useMutation(
['update avatar'],
(data: IUser) => UserService.updateAvatar(data),
{
onSuccess: ({}) => {
Toast.show({
type: 'success',
text1: 'avatar update',
text2: 'avatar update was successful'
})
}
}
)
const onSubmit: SubmitHandler<IUser> = async data => {
await mutateAsync(data)
}
return { onSubmit, isLoading, user }
}

Cannot update a component from inside the function body of a different component. how to fix this with react hook

I wanted to how to solve this error... this is not my code I am fixing bugs in someone else's code. "I wanted to how to dispatch to store with use effect Hook".
as I researched it says it says I can dispatch to store inside a function without a use effect Hook I wanted to know how to modify it in this code,
also if someone know how to getrid of "MapStateToProps" with the useSelect hook that will also be more helpfull for me inorder to improve this code...
LoginScreen.js
import React, { Component } from 'react';
import {
View, Text,
Image,
Dimensions,
ImageBackground,
SafeAreaView,
Alert,
Modal, Button,
StatusBar,
TextInput,
TextInputComponent,
Linking,
StyleSheet
} from 'react-native';
// import { PropTypes } from 'prop-types';
// import NetInfo from "#react-native-community/netinfo";
import { widthPercentageToDP as wp, heightPercentageToDP as hp } from 'react-native-responsive-screen';
// import * as Animatable from 'react-native-animatable';
import AsyncStorage from '#react-native-community/async-storage'
import { showMessage, hideMessage } from "react-native-flash-message";
const { width, height } = Dimensions.get('window');
import styles from './styles';
import Buttons from '../../../uiElements/Buttons/RoundButtons'
import VerificationCodeText from '../../../uiElements/VerificationCodeText'
import { connect } from 'react-redux';
import startUpActions from '../../../redux/StartUp/actions';
import Loading from '../../../uiElements/Loading';
import { ScrollView, TouchableHighlight, TouchableOpacity } from 'react-native-gesture-handler';
import { textFocusColor, textDefaultColor } from '../../../contents'
import TextInputField from '../../../uiElements/TextInput';
const { loginApp, getCustomerDetailsByEmail, clearProps, getAgentExposableId } = startUpActions;
const imageWidth = Dimensions.get('window').width;
// const imageWidth = Dimensions.get('window').width;
class StartScreen extends Component {
constructor(props) {
super(props);
this.state = {
hasFocusPhoneNo: false,
iseyeactivenew: true,
iseyeactivecurrent: true,
userId: '',
password: '',
hasFocusUsername: false,
hasFocusPassword: false,
}
}
static getStateFromProps(props, state) {
if (props.jwttoken != undefined) {
if (props.jwttoken == 'errlogin') {
}
}
}
static getDerivedStateFromProps(props, state) {
if (props.jwttoken != undefined) {
if (props.jwttoken == 'errlogin') {
showMessage({
textStyle: { paddingLeft: 10 },
titleStyle: { paddingLeft: 10 },
message: "Error",
description: "Username or Password incorrect",
type: "default",
backgroundColor: "red", // background color
color: "#ffffff",
duration: 3850
});
_storeAccess = async () => {
props.dispatch(clearProps())
}
_storeAccess()
} else {
_storeAccess = async () => {
await AsyncStorage.setItem('access_token', props.jwttoken);
const appIdRequest = await AsyncStorage.getItem('appIdrequest')
props.dispatch(getCustomerDetailsByEmail(props.jwttoken, '', state.userId))
//props.dispatch(clearProps())
}
_storeAccess();
}
}
if (props.customerDetailsAllResult != undefined) {
// console.log(props.customerDetailsAllResult.responseDto.customerDetailsId)
if (props.customerDetailsAllResult.responseDto == null) {
props.dispatch(clearProps())
} else {
_storeAccess = async () => {
await AsyncStorage.setItem('customerWalletId', props.customerDetailsAllResult.responseDto.agentSenderDetailsId.toString());
await AsyncStorage.setItem('email', props.customerDetailsAllResult.responseDto.email.toString()) //not change
await AsyncStorage.setItem('useremail', props.customerDetailsAllResult.responseDto.email.toString()) //when change coporate mail this will change
await AsyncStorage.setItem('agentSenderDetails', JSON.stringify(props.customerDetailsAllResult.responseDto))
const access_token = await AsyncStorage.getItem('access_token')
Console.log("navigate", access_token)
if (access_token != null) {
props.navigation.navigate('TabView')
}
// props.navigation.navigate('MoneyTransfer2')
props.dispatch(clearProps())
}
_storeAccess();
}
}
if (props.agentExposableId != undefined) {
if (props.agentExposableId == null) {
props.dispatch(clearProps()) //loginurl https://qabankingauth.monexfintech.com/v1/auth/authenticate
} else {
_storeAccess = async () => { await AsyncStorage.setItem('agentExposableId', props.agentExposableId); }
// props.navigation.navigate('MoneyTransfer2')
props.dispatch(clearProps())
}
_storeAccess();
}
return null;
}
componentDidMount() {
// console.log('lll')
}
componentDidUpdate(prevProps, prevState) {
if (prevProps.customerDetailsAllResult !== this.props.customerDetailsAllResult) {
}
if (prevProps.jwttoken !== this.props.jwttoken) {
console.log(this.props.jwttoken)
}
}
getData = async () => {
try {
const accesstoken = await AsyncStorage.getItem('access_token')
if (accesstoken !== null) {
this.props.dispatch(userShow(accesstoken))
this.setState({ islogin: true })
console.log('jjj')
// this.props.navigation.navigate('TabView')
} else {
this.props.dispatch(getBranchesList())
this.setState({ islogin: false })
// this.props.navigation.navigate('TabView')
}
} catch (e) {
console.log(e)
}
}
onChangeText = (key, val) => {
this.setState({ [key]: val }, () => {
})
}
onpressphoneno = () => {
this.setState({ hasFocusPhoneNo: true })
this.setState({ postcodeerror: false })
}
btnPress = async () => {
this.props.navigation.navigate('LoginScr')
if (this.state.userId == '' || this.state.password == '') {
showMessage({
textStyle: { paddingLeft: 10 },
titleStyle: { paddingLeft: 10 },
message: "Error",
description: "Please enter Username and Password",
type: "default",
backgroundColor: "red", // background color
color: "#ffffff",
duration: 3850
});
} else {
try {
const obj = {
username: this.state.userId,
password: this.state.password,
grantType: 'Agent Customer',
agentRegNumber: 'MXAG01'
}
await AsyncStorage.setItem('email', this.state.userId);
await AsyncStorage.setItem('useremail', this.state.userId);
await AsyncStorage.setItem('password', this.state.password);
await AsyncStorage.setItem('access_token', ' eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJjaGF0aHVyYW5nYUBjb2RlbGFudGljLmNvbSIsInVzZXJfaWQiOjMsImV4cCI6MTYxNTQzODI4NywiaXNfdGZhX2VuYWJsZWQiOm51bGwsImlhdCI6MTYxNTQzNDY4NywidGZhRGVmYXVsdFR5cGUiOm51bGwsImNsaWVudF9jb2RlIjoiTU4ifQ.lncV1VQ-T0dNPsME0_FvRF-2TQShHiwP66aFoT0fhV58QaR-Sn0ZVEBPSiGxxQ9NWnzbaCpev61Hkex6EPBxNA');
// this.props.dispatch(getFirstValue());
this.props.dispatch(getAgentExposableId());
this.props.dispatch(loginApp(obj))
this.props.dispatch(clearProps());
} catch (error) {
console.log(error);
}
//this.props.navigation.navigate('LoginScr')
}
}
clickPrivacypolicy() {
Linking.canOpenURL("https://spoton.money/policy-procedures-refund-terms-gdpr").then(supported => {
if (supported) {
Linking.openURL("https://spoton.money/policy-procedures-refund-terms-gdpr");
} else {
console.log("Don't know how to open URI: " + this.props.url);
}
});
}
render() {
// const { navigate } = this.props.navigation;
return (
<SafeAreaView style={style.container}>
<ScrollView style={{ backgroundColor: '#343A4F', }}>
<View style={{ backgroundColor: '#343A4F', height: '100%' }}>
<ImageBackground source={require('../../../images/ellipse.png')} style={{ width: '100%', height: '60%' }}>
<View style={{ alignItems: 'center', paddingTop: wp('15%') }}>
<Image
style={{ width: wp('45%'), height: wp('15%') }}
source={require('../../../images/spotonmoneylogo.png')}
/>
</View>
{this.props.loading && <Loading navigation={this.props.navigation} animating={true} />}
<View style={{ paddingLeft: wp('5%'), paddingRight: wp('5%'), backgroundColor: '#343A4F', marginTop: wp('50%') }}>
{/* <TextInput
placeholder="Username"
placeholderTextColor={textDefaultColor}
onFocus={() =>this.setState({ hasFocusUsername: true })}
onBlur={() => this.setState({ hasFocusUsername: false })}
onChangeText={(val) => this.setState({ userId: val })}
style={
this.state.hasFocusUsername ?
styles.focusedTextInput :
styles.txtstyle
}
/> */}
<TextInputField
placeholdertext="Username"
valuetext={this.state.email}
onFocusFunc={() => this.setState({ hasFocusUserName: true })}
onBlurFunc={() => this.setState({ hasFocusUserName: false })}
onChangeTextFunc={value => this.onChangeText('userId', value)}
iserrortext={this.state.errorlastnamestate}
editabletext={false}
keyboardType1='email'
// texterror={this.state.errorlastnametextstate}
// hasFocustext={this.state.hasFocusUserName}
/>
<TextInputField
placeholdertext="Password"
valuetext={this.state.password}
onFocusFunc={() => this.setState({ hasFocusPassword: true })}
onBlurFunc={() => this.setState({ hasFocusPassword: false })}
onChangeTextFunc={value => this.onChangeText('password', value)}
iserrortext={this.state.errorlastnamestate}
editabletext={false}
secureTextEntrytxt={true}
// texterror={this.state.errorlastnametextstate}
hasFocustext={this.state.hasFocusPassword}
/>
{/* <TextInput
placeholder="Password"
placeholderTextColor={textDefaultColor}
secureTextEntry={true}
onFocus={() => this.setState({ hasFocusPassword: true })}
onBlur={() => this.setState({ hasFocusPassword: false })}
onChangeText={(val) => this.setState({ password: val })}
style={
this.state.hasFocusPassword ?
styles.focusedTextInput :
styles.txtstyle
}
/> */}
</View>
<View style={{ paddingTop: wp('10%'), alignItems: 'center' }}>
<TouchableOpacity onPress={() => this.props.navigation.navigate('Verification')}>
<Text style={{ color: 'white' }}>Forgot Password</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.btnPress()}>
<Buttons text="Log In" btnfontSize={wp('4%')}
btnbackgroundColor='#F15622'
btntxtncolor="#ffffff"
btnMarginRight={imageWidth / 1000}
btnMarginLeft={imageWidth / 1000}
onPress={() => this.btnPress()} />
</TouchableOpacity>
<View style={{ paddingTop: wp('4%') }}>
<Text style={{ color: 'white', fontSize: wp('4%') }}>Don't have an account?
<TouchableOpacity onPress={() => this.props.navigation.navigate('VerificationSignUp')}>
<Text style={{ color: '#2793E1', fontWeight: 'bold', textDecorationLine: 'underline' }}>
Sign Up
</Text>
</TouchableOpacity>
</Text>
</View>
<View style={{ padding: wp('4%'), marginTop: hp('4%'), alignContent: 'center' }}>
<TouchableOpacity >
<Text style={{ color: 'white', fontSize: wp('3%') }}>By logging in you agree to the Spoton money
<TouchableOpacity onPress={() => this.clickPrivacypolicy()}>
<Text style={{ color: '#2793E1', fontSize: wp('3%'), paddingTop: wp('1%') }}>
Privacy policy .
</Text>
</TouchableOpacity>
and acknowledge our
<TouchableOpacity onPress={() => this.clickPrivacypolicy()}>
<Text style={{ color: '#2793E1', fontSize: wp('3%'), paddingTop: wp('1%') }}>
Terms & Conditions.
</Text>
</TouchableOpacity>
</Text>
</TouchableOpacity>
</View>
</View>
</ImageBackground>
</View>
</ScrollView>
</SafeAreaView>
);
}
}
const mapStateToProps = state => {
return {
...state.startUpReducer
}
// loading: state.startUpReducer.loading,
// jwttoken: state.startUpReducer.jwttoken,
// customerDetailsAllResult: state.startUpReducer.customerDetailsAllResult,
// agentExposableId: state.startUpReducer.exposable_id
};
export default connect(mapStateToProps)(StartScreen);
const style = StyleSheet.create({
container: {
backgroundColor: '#343A4F',
height: wp()
}
})
redux/Actions.js
loginApp: (value) => ({
type: actions.LOGIN_SCREEN,
value
}),
redux/reducer.js
case startUpActions.LOGIN_SCREEN:
return{
...state,
loading:true
}
case startUpActions.LOGIN_SCREEN_RESULT:
return{
loading:false,
jwttoken:action.result.jwttoken
}
case startUpActions.LOGIN_SCREEN_ERROR:
return{
loading:false,
jwttoken:'errlogin'
}
redux/saga.js
export function* loginApp(){
yield takeEvery(actions.LOGIN_SCREEN, function* (payload) {
const requestBody=payload.value
const url = loginURL;
console.log(requestBody);
console.log(url);
try {
const response = yield fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(requestBody)
});
console.log(response)
const result = yield response.json();
console.log(result)
if (response.ok) {
yield put({ type: actions.LOGIN_SCREEN_RESULT, result });
} else {
yield put({
type: actions.LOGIN_SCREEN_ERROR,
result
});
}
} catch (error) {
yield put({ type: actions.LOGIN_SCREEN_ERROR });
}
});
}

undefined is not an object (evaluating 'this.state.user.avatar')

Image of Error
I am using ios emulator and keep on receiving this error when i go to run the profile page. It first loads for a little bit then stops and the error pops up it says it's on the 'this.state.user.avatar' but i can't seem to see what i wrong with it? what am i doing wrong? if someone can help me that would be great!
This is my ProfileScreen.js file
import React from "react";
import {View, Text, StyleSheet, TouchableOpacity, Button, Image } from "react-native";
import Fire from '../utilities/Fire';
export default class ProfileScreen extends React.Component {
state = {
user: {}
};
unsubscribe = null;
componentDidMount() {
const user = this.props.uid || Fire.shared.uid
this.unsubscribe = Fire.shared.firestore
.collection("users")
.doc(user)
.onSnapshot(doc => {
this.setState({ user: doc.data() });
});
}
componentWillUnmount() {
this.unsubscribe();
};
render() {
return(
<View style={styles.container}>
<View style = {{ MarginTop: 64, alignItems: "Center" }}>
<View style={styles.avatarContainer}>
<Image style={styles.avatar} source={this.state.user.avatar ? { uri: this.state.user.avatar } : require("../assets/avatar.png")}
/>
</View>
<Text style={styles.name}>{this.state.user.name}</Text>
</View>
<View style={styles.subContainer}>
<View style={styles.stat}>
<Text style={styles.info}>8/10</Text>
<Text style={styles.Title}>Rewards</Text>
</View>
<View style={styles.stat}>
<Text style={styles.info}>80/100</Text>
<Text style={styles.Title}>Badges</Text>
</View>
</View>
<Button onPress={() => {Fire.shared.signOUt()}} title="Log Out" />
</View>
);
}
}
const styles = StyleSheet.create({
container:{
flex: 1,
},
avatarContainer:{
shadowColor: "#151734",
shadowRadius: 15,
shadowOpacity: 0.4
},
avatar: {
width: 136,
height: 136,
borderRadius: 68
},
name: {
marginTop: 24,
fontSize: 16,
fontWeight: "600"
},
subContainer: {
flexDirection: "row",
justifyContent: "space-between",
margin: 32,
},
stat: {
alignItems:"center",
},
info: {
color: "#4F566D",
fontSize: 18,
fontWeight: "300"
},
Title: {
color: "#C3C5CD",
fontSize: 12,
fontWeight: "500",
marginTop: 4
}
});
This is my Fire.js file
import FirebaseKeys from '../config';
import firebase from 'firebase';
require("firebase/firestore");
class Fire{
constructor() {
firebase.initializeApp(FirebaseKeys);
}
addPost = async({ text, localUri }) => {
const remoteUri = await this.uploadPhotoAsync(localUri, 'photos/${this.uid}/${Date.now()}');
return new Promise ((res, rej) => {
this.firestore
.collection("posts")
.add ({
text,
uid: this.uid,
timestamp: this.timestamp,
image: remoteUri
})
.then(ref => {
res(ref);
})
.catch(error => {
rej(error);
});
});
};
uploadPhotoAsync = async (uri, filename) => {
return new Promise(async (res, rej) => {
const response = await fetch(uri);
const file = await response.blob();
let upload = firebase
.storage()
.ref(filename)
.put(file);
upload.on(
"state_changed",
snapshot => {},
err => {
rej(err);
},
async () => {
const url = await upload.snapshot.ref.getDownloadURL();
res(url);
}
);
});
};
createUser = async user => {
let remoteUri = null
try {
await firebase.auth().createUserWithEmailAndPassword(user.email, user.password)
let db = this.firestore.collection("users").doc(this.uid)
db.set({
name: user.name,
email: user.email,
avatar: null
})
if (user.avatar) {
remoteUri = await this.uploadPhotoAsync(user.avatar, 'avatars/${this.uid}')
db.set({avatar: remoteUri }, { merge: true})
}
} catch (error) {
alert("Error: ", error);
}
};
signOut = () => {
firebase.auth().signOut();
};
get firestore(){
return firebase.firestore();
}
get uid() {
return (firebase.auth().currentUser || {}).uid;
}
get timestamp() {
return Date.now();
}
}
Fire.shared = new Fire();
export default Fire;
If you want to set the state like that you need to do it in the constructor like this:
constructor(props) {
super(props);
this.state = {
user: {}
}
}
So add that code to the top of the class and it should actually set the user to an empty object..
Everywhere else in the app you use setState....
Try to change user{} by user[]

React Native: Maximum update depth exceeded error

Am getting Maximum update depth exceeded error while entering values into the text field . This is my component .
If i remove the onChangeText event it wont throw error, so the issue is with the event .
These are the dependencies am currently using
react : 16.8.6,
react-dom :16.8.6,
react-native :https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz,
import { Form, View, Text, Button, Item, Input, Label, Toast, Spinner } from "native-base";
import React from "react";
import { validatePin } from "../services/validate";
export default class LoginForm extends React.Component {
constructor(props) {
super(props);
this.state = { userid: "", loading: "false" };
}
async login() {
if (this.state.userid.length == 0) {
Toast.show({
text: "Wrong UserID!",
buttonText: "Okay",
textStyle: { color: "yellow" }
});
} else {
if(this.state.loading === "false" ){
this.setState({ loading: "true" });
}
try {
let res = await validatePin(this.state.userid);
if (typeof res != "undefined") {
const { navigate } = this.props.navigation;
this.setState({ loading: "false" });
if (res.bypassMFA) {
navigate("Password", {
user_id: this.state.userid,
member_name: res.member_name
});
} else {
navigate("MFAComponent", {
userid: this.state.userid,
mfa_id: res.mfa_id,
mfa_q: res.mfa_q,
isValidUser: res.isValidUser
});
}
}
} catch (err) {
console.log("error in login:" + err);
}
}
}
render() {
const { navigate } = this.props.navigation;
return (
<View>
<Form style={{ padding: 5, alignItems: "center" }}>
<Item floatingLabel>
<Label>Online ID</Label>
<Input
value={this.state.userid}
onChangeText={username => this.setState({ userid: username })}
/>
</Item>
{this.state.loading == "true" ? (
<View>
<Spinner size="large" color="#c137a2" />
</View>
) : null}
<Button primary onPress={this.login} style={{ alignSelf: "center", margin: 20 }}>
<Text> Next </Text>
</Button>
</Form>
</View>
);
}
}
First of all you didn't bind login function for onPress. Your onPress props should be like this :
onPress={() => this.login}
or in constructor bind method :
this.login.bind(this)

React Native Failed to ImportScripts Error

I'm getting an ImportScripts error which means I'm not importing or exporting something correctly I'm guessing. I've narrowed it down to the import { getPath } from '~/redux/modules/camera' line. But I'm not sure why I get an error. I import connect so I have access to dispatch and then I import the getPath function. What else should I be doing? Thanks!
import React, { PropTypes, Component } from 'react';
import {
Dimensions,
StyleSheet,
Text,
TouchableHighlight,
View
} from 'react-native';
import Camera from 'react-native-camera'
import { connect } from 'react-redux'
import { getPath } from '~/redux/modules/camera'
class NimbusCamera extends Component {
static propTypes = {
navigator: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired,
}
state = {
camera: {
aspect: Camera.constants.Aspect.fill,
captureTarget: Camera.constants.CaptureTarget.disk,
type: Camera.constants.Type.front,
orientation: Camera.constants.Orientation.auto,
flashMode: Camera.constants.FlashMode.auto,
}
isRecording: false,
timeLeft: 30,
limitReached: false
}
render() {
console.log(this.props)
return (
<View style={styles.container}>
<Camera
ref={(cam) => {
this.camera = cam;
}}
style={styles.preview}
aspect={this.state.camera.aspect}
type={this.state.camera.type}
captureTarget={this.state.camera.captureTarget}
captureAudio={true}
flashMode={this.state.camera.flashMode}
>
<Text style={styles.capture} onPress={this.startRecording.bind(this)}>[CAPTURE]</Text>
<Text style={styles.capture} onPress={this.stopRecording.bind(this)}>[STOP_RECORDING]</Text>
</Camera>
</View>
);
}
startRecording = () => {
if (this.camera) {
this.camera.capture({mode: Camera.constants.CaptureMode.video})
.then((data) => console.log(data))
.catch(err => console.error(err));
this.setState({
isRecording: true
});
let timerId = setInterval(countdown, 1000);
function countdown() {
if (this.state.timeLeft === 0) {
clearTimeout(timerId);
this.setState({isRecording: false})
} else {
this.setState({timeLeft: this.state.timeLeft--})
}
}
}
}
stopRecording = () => {
if (this.camera) {
this.camera.stopCapture();
this.setState({
isRecording: false
});
}
}
}
export default connect()(NimbusCamera)
const styles = StyleSheet.create({
container: {
flex: 1
},
preview: {
flex: 1,
justifyContent: 'flex-end',
alignItems: 'center',
height: Dimensions.get('window').height,
width: Dimensions.get('window').width
},
capture: {
flex: 0,
backgroundColor: '#fff',
borderRadius: 5,
color: '#000',
padding: 10,
margin: 40
}
});
Here is my redux camera module.
const GET_PATH = 'GET_PATH'
const CLEAR_PATH = 'CLEAR_PATH'
initialState = {
videoPath: ''
}
export function getPath (path) {
return {
type: GET_PATH,
path
}
}
export function clearPath () {
return {
type: CLEAR_PATH
}
}
export default function camera (state = initialState, action) {
switch (action.type) {
case GET_PATH :
return {
...state,
videoPath: action.path
}
case CLEAR_PATH :
return {
...state,
videoPath: ''
}
default :
return state
}
}
Any log in your packager console? usually it print much more detail error info.
errors like these pops-up also when you make a typo in your code. Then module cannot be properly imported. Check your code for typos first :)

Resources