I am using firebase in a react native app along with the spinner from 'react-native-loading-spinner-overlay'.
Im trying to show the spinner while the user is authenticating to firebase but the spinner isn't showing up. This is the function that handles an user trying to auth:
const [spinnerState, setSpinnerState] = useState(false)
...
const handleAuthenticationAttempt = () => {
if (emailStatus == false || passwordStatus == false) {
Alert.alert(
"ERROR",
"Something went wrong... Please make sure you have inserted all data correctly.",
[{
text: "OK",
style: "ok",
}])
} else {
const auth = getAuth(app);
setSpinnerState(true)
signInWithEmailAndPassword(auth, email, password)
.then(() => {
setSpinnerState(false)
console.log("success")
})
.catch((error) => {
Alert.alert(
"ERROR",
"Something went wrong... Please check the email and password you entered is correct: " + error.code,
[{
text: "OK",
style: "ok",
}])
})
}
}
This is my render:
<View style={styles.container}>
<Spinner
visible={spinnerState}
textContent={'Loading...'}
textStyle={{ color: 'rgb(200, 200, 200)' }} />
<View style={styles.containerSvg}>
<LinearBackground />
</View>
<TouchableWithoutFeedback onPress={Keyboard.dismiss} accessible={false}>
<View style={styles.containerAlign}>
// OTHER INPUTS
<ButtonAction onPress={handleAuthenticationAttempt} text={'LOGIN'} backgroundColor='rgba(20, 120, 160, 0.6)' />
</View>
</TouchableWithoutFeedback>
</View>
In theory this should work but it doesn't.
I have changed the spinner location multiple times but it never seems to show up. Any ideas on what's going on?
EDIT: Even when using setTimeout, the spinner never actually shows up.
Fixed it, had to use conditional rendering, which is quite strange considering other snack examples using what I had above worked.
{loadingStatus && <Spinner
visible={true}
textContent={'Loading...'}
textStyle={{
color: '#FFF'
}} />
}
Related
I'm facing an issue from axios which is returning a 404 error on api call. This
API end point is already using many times in my application but in a particular scenario this API is returning 404 error status in catch block. Here is the scenario..
I have created an invite link to my application and when a user click on the invite link they will redirect to the Application and on startup I'm displaying a popup component with buttons. when the user click the button to join a particular event on the Application axios patch request is returning 404 error status on catch block. But in other cases this API is working fine. Anybody knows how this is happening..
here is the code sample
{gameId != "" &&
<GameInvitationPopup
id={gameId}
setGameId={setGameId}
/>
}
When we click on the GameInvitation pupup,
<View style={{ alignItems: 'center', marginVertical: 20 }}>
<Text style={styles.h3Black}>Will you join the game?</Text>
<View style={[styles.rowFlex, { marginTop: 10 }]}>
<TouchableOpacity
onPress={() => updateGameData(1)}
activeOpacity={0.6}
style={styles.yesView}>
<Text style={styles.h3Medium}>Yes</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => updateGameData(2)}
activeOpacity={0.6}
style={styles.noView}>
<Text style={styles.h3Medium}>No</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => updateGameData(3)}
activeOpacity={0.6}
style={styles.maybeView}>
<Text style={styles.h3Medium}>Maybe</Text>
</TouchableOpacity>
</View>
</View>
When we click on the updateGameData function,
const updateGameData = (stat) => {
setLoading(true)
gameStatusUpdateApiNw(id, stat)
.then((out) => {
setGameId("")
setLoading(false)
setShowAlert(true)
})
.catch(() => {
setLoading(false)
})
}
This is the API request code, this API is a working API and and the body provide is correct, but still I'm getting 404 error status,
const gameStatusUpdateApiNw = async (id, status) => {
const state = store.default.getState();
const token = state.authReducer.authToken;
const url = `${BASE_URL}/api/games/status/${id}`;
console.log('status url is ', url);
try {
const {data} = await patchRequest(
url,
{status: status},
{
headers: {
Authorization: `Bearer ${token}`,
},
},
);
console.log('data game ', data);
return data;
} catch (e) {
throw e;
}
};
Anybody knows how this error occur in a working API when we provide correct body into it. Please help
I am trying to resolve the error Non-serializable values were found in the navigation state. Alert > params.action[0].onPress (Function) of React Native navigation. I don't think the function is not passed to the param like the error points out, but it kept returning this same error every time I pressed the icon. I'd appreciate any suggestions or comments.
export default function Alert({ route, navigation }) {
const { colors } = useTheme();
const { t } = useTranslation();
const { title, message, action, option, type } = route?.params;
const success = type === "success";
useEffect(() => {
const backHandler = BackHandler.addEventListener(
"hardwareBackPress",
() => !option?.cancelable
);
return () => backHandler.remove();
}, [option?.cancelable]);
const renderButtonFirst = () => {
const firstTitle = action?.[0]?.text ?? t("close");
const onPressNo = action?.[0];
return (
<TouchableOpacity
onPress={() => {
onPressNo?.onPress();
if (option?.cancelable) navigation.goBack();
}}
>
<Text>
{firstTitle}
</Text>
</TouchableOpacity>
);
};
const renderButtonSecond = () => {
const secondTitle = action?.[1]?.text;
const onPressYes = action?.[1];
if (title && onPressYes) {
return (
<TouchableOpacity
onPress={() => {
onPressYes?.onPress();
if (option?.cancelable) navigation.goBack();
}}
>
<Text>
{secondTitle}
</Text>
</TouchableOpacity>
);
}
};
return (
<View>
<Icon name={success ? "check-circle" : "question-circle"} />
</View>
<View>
<Text>
{title}
</Text>
<Text>
{message}
</Text>
</View>
<View >
{renderButtonFirst()}
{renderButtonSecond()}
</View>
</View>
</View>
);
}
And this is the parent component just in case. But this error is from the Alert component as it says.
const onOpen = (type, title, link) => {
Alert.alert({
title: title,
message: `${t("do_you_want_open")} ${title} ?`,
action: [
{
text: t("cancel"),
onPress: () => console.log("Cancel Pressed"),
style: "cancel",
},
{
text: t("done"),
onPress: () => {
switch (type) {
case "web":
Linking.openURL(link);
break;
case "phone":
Linking.openURL("tel://" + link);
break;
case "email":
Linking.openURL("mailto:" + link);
break;
case "address":
Linking.openURL(link);
break;
}
},
},
],
});
};
{product?.website.length > 0 && (
<TouchableOpacity
onPress={() => {
onOpen("web", t("Website"), product?.website);
}}
>
<View>
<Image
source={Images}
/>
</View>
</TouchableOpacity>
)}
UPDATE 4/1
This is the Navigation component just in case;
import AlertScreen from "#screens/Alert";
export default function Navigator() {
...
return (
<AppearanceProvider>
<NavigationContainer theme={theme}>
<RootStack.Screen
name="Alert"
component={AlertScreen}
gestureEnabled: false,
}}
/>
</RootStack.Navigator>
</NavigationContainer>
</AppearanceProvider>
);
}
From the react navigation docs
This can happen if you are passing non-serializable values such as
class instances, functions etc. in params. React Navigation warns you
in this case because this can break other functionality such state
persistence, deep linking etc.
If you don't use state persistence or deep link to the screen which
accepts functions in params, then the warning doesn't affect you and
you can safely ignore it. To ignore the warning, you can use
YellowBox.ignoreWarnings.
If you are using react-native version > 0.63, use:
import { LogBox } from 'react-native';
LogBox.ignoreLogs([ 'Non-serializable values were found in the
navigation state', ]);
I also got bitten by this. You cannot pass non-simple objects to the navigation.
The problem is not "directly" in the code you posted but somewhere else. Either the go-back triggered the problem "once more" or there is somewhere a line like:
navigation.navigate('Alert', { action: {onPress: some_function }, /* rest */ }
In any case, the problem is that action comes from the parameters and is expected to have am onPress function. You cannot serialize a function an thus cannot model it like that.
Solution: Put that logic into a service and the parameters into the route, something like:
export Service {
do(actionDescription: {type: string, payload: any}) {
if (actionDescription.type === 'log') console.log(actionDescription.payload); // you get the idea
}
}
// in Alert
const onPressNo = () => Service.do(action?.[0].action);
// somewhere:
navitation.navigate('Alert', {action: [{action: {type: 'log', payload: 'Cancel Pressed'} /* complete... */]
So, past only simple objects to the navigation route. Use a pseudo-Command pattern, where the command state is passed into the route and the trigger is centralized somewhere else.
I'm attempting to create a simple app that allows users to register and login using Firebase as a backend.
I'm using Stephen Grider-ReactNativeCasts as a template and I implemented firebase as the backend somewhat successfully I think. I am able to signup and the user shows up in the user list on the firebase dashboard, but when I attempt to sign in I get the error: Undefind is not object (evaluating 'this.props.navigator').
This is what my signin looks like,
var React = require('react-native');
var Firebase = require('firebase');
var {
View,
Text,
StyleSheet,
TextInput
} = React;
var Parse = require('parse/react-native');
var Button = require('../common/button');
module.exports = React.createClass({
getInitialState: function() {
return {
email: '',
password: '',
errorMessage: ''
};
},
render: function() {
return (
<View style={styles.container}>
<Text>Sign In</Text>
<Text style={styles.label}>Email:</Text>
<TextInput
style={styles.input}
value={this.state.email}
onChangeText={(text) => this.setState({email: text})}
/>
<Text style={styles.label}>Password:</Text>
<TextInput
secureTextEntry={true}
style={styles.input}
value={this.state.password}
onChangeText={(text) => this.setState({password: text})}
/>
<Text style={styles.label}>{this.state.errorMessage}</Text>
<Button text={'Sign In'} onPress={this.onPress} />
<Button text={'I need an account...'} onPress={this.onSignupPress} />
</View>
);
},
onSignupPress: function() {
this.props.navigator.push({name: 'signup'});
},
onPress: function() {
var ref = new Firebase("https://reactapplogin.firebaseio.com");
ref.authWithPassword({
email : this.state.email,
password : this.state.password
}, function(error, authData) {
if (error) {
console.log("Login Failed!", error);
} else {
console.log("Authenticated successfully with payload:", authData);
this.props.navigator.immediatelyResetRouteStack({name: 'tweets'});
}
});
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
input: {
padding: 4,
height: 40,
borderColor: 'gray',
borderWidth: 1,
borderRadius: 5,
margin: 5,
width: 200,
alignSelf: 'center'
},
label: {
fontSize: 18
}
});
I'm having issue with this.props.navigator.immediatelyResetRouteStack({name: 'tweets'}); not working, and I also have zero idea where these console logs show up in the emulator (using Genymotion/Android Studio Emulators) so debugging is proving a little hard. I've tried to connect to chrome but it keeps failing.
Anyhelp would be really appreciated!
Thanks!
Stephen's project Github Page: https://github.com/StephenGrider/ReactNativeCasts/tree/master/authentication
The problem is not with Firebase but with your implementation.
You don't have the navigator on your props because you are not using a navigator. In Stephen's project Github Page you can see the Navigator is rendered and the components get the navigator prop.
renderScene: function(route, navigator) {
var Component = ROUTES[route.name]; // ROUTES['signin'] => Signin
return <Component route={route} navigator={navigator} />;
},
render: function() {
return (
<Navigator
style={styles.container}
initialRoute={{name: 'signin'}}
renderScene={this.renderScene}
configureScene={() => { return Navigator.SceneConfigs.FloatFromRight; }}
/>
);
update
Take a look at the src/main.js.
The rendered component is the react-native Navigator. on the navigator you have a renderScene prop that calls renderScene function which returns the correct component according to the ROUTES object and passes it the navigator as a prop.
Make the below change and your program should work, immediatelyResetRouteStack accepts an array not an object
this.props.navigator.immediatelyResetRouteStack({name: 'tweets'}); // wrong
this.props.navigator.immediatelyResetRouteStack([{name: 'tweets'}]); // right
I would like to have two text fields:
one that accepts a title
another that accepts a body (i.e. more text)
...and a submit button:
that saves the title and body that was entered, when clicked
I have researched TextInput, AsyncStorage, TouchableHighlight and Navigator components as well as a bunch of react-native tutorials. I can't seem to find any consistency - not even from the react-native docs.
Here is what I have so far:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
AsyncStorage,
TextInput,
TouchableHighlight
} from 'react-native';
class PostAndSave extends Component {
constructor(props) {
super(props);
this.state = {
messageTitle: '',
messageBody: ''
}
}
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Walker app
</Text>
<TextInput
placeholder="Title"
style={{height: 40, borderColor: 'gray', borderWidth: 1}}
onChange={(event) => this.setState({messageTitle: event.nativeEvent.text})}
value={this.state.messageTitle} />
<TextInput
placeholder="Body"
style={{height: 40, borderColor: 'gray', borderWidth: 1}}
onChange={(event) => this.setState({messageBody: event.nativeEvent.text})}
value={this.state.messageBody} />
<TouchableHighlight onPress={this._onPressButton} style={styles.button}>
<Text style={styles.buttonText}>See all posts</Text>
</TouchableHighlight>
</View>
);
}
}
// styles here
AppRegistry.registerComponent('PostAndSave', () => PostAndSave);
I can type into the input fields but cannot figure AsyncStorage out, or how to post new messages as opposed to the overwriting the existing one. I'm mainly looking for help in that area - below I have posted my goal incase the question of why I want to do this comes up.
Goal:
The saved 'post' should then be printed to a view, where it can be pressed (tapped?) to display the contents of the body.
Each time a title and body are submitted they should be saved as a new 'post' and not overwritten.
If you want to use Async for this you'll need a function to save the data:
_onPressButton () {
// Get the data
let title = this.state.messageTitle
let message = this.state.messageBody
// Retrieve the existing messages
AsyncStorage.getItem('messages', (res) => {
var messages
// If this is the first time, set up a new array
if (res === null) {
messages = []
}else {
messages = JSON.parse(res)
}
// Add the new message
messages.push({
title: title,
message: message
})
// Save the messages
AsyncStorage.setItem('messages', JSON.stringify(messages), (res) => {})
}
}
And you'll want to bind this to your instance:
<TouchableHighlight onPress={this._onPressButton.bind(this)} style={styles.button}>
And to retrieve your messages for use later:
AsyncStorage.getItem('messages', (res) => {
this.setState({
messages: res
})
})
I am having trouble with my ability to get the AccessToken in the fbsdk in React Native.
I am calling the core as suggested by Facebook:
const FBSDKCore = require('react-native-fbsdkcore');
const {
FBSDKAccessToken,
} = FBSDKCore;
And in one scenario I try to write the token in the log as suggested by a similair question stated here on SO.
<View>
<View style={{flex: 1, alignItems: 'center', padding: 50, marginTop: 250}}>
<View>
<LoginButton
publishPermissions={["publish_actions"]}
onLoginFinished={
(error, result) => {
if (error) {
alert("login has error: " + result.error);
} else if (result.isCancelled) {
alert("login is cancelled.");
} else {
FBSDKAccessToken.getCurrentAccessToken((token)=> {
console.log(token);
});
Actions.Navigator()
}
}
}
onLogoutFinished={() => {
alert("logout.")}}/>
</View>
</View>
</View>
This gives me the redscreen "undefined is not an object (evaluating the FBSDKAccessTokenInterface.getCurrentAccessToken)
Trying to pull off something similair in other parts of the app, of course defining the const FBSDKAccessToken first, then calling the userID (which should be a part of the FBSDKCore) as:
<Text style={{fontSize: 18, color:colors.General.navtext}}>{FBSDKAccessToken.userID}</Text>
Yields nothing, where I believed it to return the userID of the logged in user. Also, if I try to write out the accesstoken in that same place as:
<Text style={{fontSize: 18, color:colors.General.navtext}}>{FBSDKAccessToken.getCurrentAccessToken()}</Text>
I get the same red screen as before.
I tried to look in to the linking of libraries, but that even caused further problem.
Hence, from this, I am pretty stranded and I would really appreciate some feedback on what has gone wrong.
Try this.
console.log(token.accessToken.toString());