Deleting account/user in firebase using REST API - firebase

I trying to delete an account in firebase using REST API, axios and React Native?
Look at my code:
import React, {Component} from 'react'
import {View, Text, TouchableOpacity, StyleSheet} from 'react-native'
import axios from 'axios'
class App extends Component {
deleteAccount = () => {
axios.post('https://identitytoolkit.googleapis.com/v1/accounts:delete?key=[API_KEY]', {
"idToken":"[FIREBASE_ID_TOKEN]"
})
}
render() {
return(
<View style={styles.container}>
<TouchableOpacity onPress={this.deleteAccount}>
<Text>Button</Text>
</TouchableOpacity>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
}
})
export default App
PS.: Maybe, I'm puting the wrong FIREBASE_ID_TOKEN
Where can I get the right FIREBASE_ID_TOKEN?
Reference: https://firebase.google.com/docs/reference/rest/auth?hl=pt-br#section-delete-account
Thanks!

The ID token you need to use comes from User#getIdToken(). This function returns a Promise containing the user's ID token that you then send off to the Identity Toolkit API.
Make sure to replace [API_KEY] with the Web API Key that you'll find on the project settings page.
deleteAccount = () => {
firebase.auth().currentUser.getIdToken(/* forceRefresh */ true)
.then((userIdToken) => {
return axios.post('https://identitytoolkit.googleapis.com/v1/accounts:delete?key=[API_KEY]', {
"idToken": userIdToken
});
})
.then(function (response) {
console.log(response);
// TODO: update UI that account was deleted
})
.catch(function (error) {
console.log(error);
// TODO: update UI that operation failed
});
}

Related

React Native Expo Google Sigin Using expo-auth-session redirect issue

I am using expo-auth-session for Google login in Expo App. But when try to hit the login button I am getting redirect URI mismatch issue. Any help would be appreciated. Below
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, View, Text, Image, Button } from 'react-native';
import * as Google from 'expo-auth-session/providers/google';
import * as WebBrowser from 'expo-web-browser';
WebBrowser.maybeCompleteAuthSession();
const LoginScreen = () => {
const [accessToken, setAccessToken] = React.useState();
const [userInfo, setUserInfo] = React.useState();
const [message, setMessage] = React.useState();
const [request, response, promptAsync] = Google.useAuthRequest({
androidClientId: "androidClientId",
iosClientId: "iosClientId",
expoClientId: "expoClientId"
});
React.useEffect(() => {
setMessage(JSON.stringify(response));
if (response?.type === "success") {
setAccessToken(response.authentication.accessToken);
}
}, [response]);
async function getUserData() {
let userInfoResponse = await fetch("https://www.googleapis.com/userinfo/v2/me", {
headers: { Authorization: `Bearer ${accessToken}` }
});
userInfoResponse.json().then(data => {
setUserInfo(data);
});
}
function showUserInfo() {
if (userInfo) {
return (
<View style={styles.userInfo}>
<Image source={{ uri: userInfo.picture }} style={styles.profilePic} />
<Text>Welcome {userInfo.name}</Text>
<Text>{userInfo.email}</Text>
</View>
);
}
}
return (
<View style={styles.container}>
{showUserInfo()}
<Button
title={accessToken ? "Get User Data" : "Login"}
onPress={accessToken ? getUserData : () => { promptAsync({ useProxy: false, showInRecents: true }) }}
/>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
userInfo: {
alignItems: 'center',
justifyContent: 'center',
},
profilePic: {
width: 50,
height: 50
}
});
export default LoginScreen;
I have lost around 2 days and I wasn't able to configure it properly. I ended up using this package instead: https://docs.expo.dev/versions/latest/sdk/google-sign-in/
I know it's deprcated, but when I've done all setup following instructions everything started to work.
I will be following if there are some updates in next expo sdk version, but right now it's not working as expected :(
Edit:
In expo go everything was working fine, but in standalone app it wasn't working

Expo ReactNative Firebase Get authenticated user and profile in one go

I am new to Expo and ReactNative. At the moment, I am developing a mobile app that utilizes Firebase Auth and Firestore for authentication and user profile. From googling, I found a solution to use ContextProvider for the Firebase Auth. I tried to adjust the code to obtain the profile at the same time.
This is the code for AuthenticatedUserProvider.js
import React, { useState, createContext } from 'react';
export const AuthenticatedUserContext = createContext({});
export const AuthenticatedUserProvider = ({ children }) => {
const [user, setUser] = useState(null);
const [profile, setProfile] = useState(null);
return (
<AuthenticatedUserContext.Provider value={{ user, setUser, profile, setProfile }}>
{children}
</AuthenticatedUserContext.Provider>
);
};
And I read the profile on the RotNavigator.js below
import React, { useContext, useEffect, useState } from 'react';
import { View, ActivityIndicator } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import * as eva from '#eva-design/eva';
import { ApplicationProvider, IconRegistry } from '#ui-kitten/components';
import { EvaIconsPack } from '#ui-kitten/eva-icons';
import { auth, fs } from '../config/firebase';
import { AuthenticatedUserContext } from './AuthenticatedUserProvider';
import AuthStack from './AuthStack';
import HomeStack from './HomeStack';
import { default as theme } from '../orange-theme.json';
export default function RootNavigator() {
const { user, setUser, profile, setProfile } = useContext(AuthenticatedUserContext);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
// onAuthStateChanged returns an unsubscribe
const unsubscribeAuth = auth.onAuthStateChanged(async authenticatedUser => {
try {
if (authenticatedUser) {
await setUser(authenticatedUser)
const response = await fs.collection("members").doc(authenticatedUser.uid).get();
if (response.exists) {
let data = response.data();
// console.log(data);
await setProfile(data);
// console.log(profile);
}
} else {
await setUser(null);
await setProfile(null);
}
setIsLoading(false);
} catch (error) {
console.log(error);
}
});
// unsubscribe auth listener on unmount
return unsubscribeAuth;
}, []);
if (isLoading) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size='large' />
</View>
);
}
return (
<>
<IconRegistry icons={EvaIconsPack} />
<ApplicationProvider {...eva} theme={{ ...eva.light, ...theme }}>
<NavigationContainer>
{user ? <HomeStack /> : <AuthStack />}
</NavigationContainer>
</ApplicationProvider >
</>
);
}
The code looks like working except that if I log in, sometimes I saw an error on profile = null and cannot read the profile but then it refreshed by itself and back to run properly.
Can someone suggest the correct way to display the profile from Firestore?
The reason I do it like this is I want an efficient way of displaying the profile since HomeStack has 3 screens that would need to display some parts of the profile on each screen.
Thank you for your help.

unable to manage state using redux in react native project

I'm new to react native development. And I have created this sample note application using Redux for react native. In this application user must be able to add a note and that note needs to be managed via redux store.
And I have created required action and reducer for adding note functionality.
However I was not able to add a new note to the store. I tried debugging and when it reaches the "ADD_Note" case in reducer, it jump into default case automatically. And whatever the string value or note that pass via action, it becomes 'undefined' in the reducer.
Please refer my code for adding note screen
import React, {useState, useEffect} from 'react';
import {
StyleSheet,
View,
Text,
TextInput,
Button,
FlatList,
} from 'react-native';
import {useSelector, useDispatch} from 'react-redux';
import * as NoteActions from '../store/actions/Note'; // import note actions
const NoteScreen = () => {
const [note, setNote] = useState('');
const dispatch = useDispatch(); // use dispatch
const noteHandler = text => {
setNote(text);
};
return (
<View style={styles.container}>
<View>
<TextInput
style={styles.textInput}
placeholder="Enter a note"
onChangeText={noteHandler}
value={note}
/>
<Button
title="Add"
onPress={() => {
console.log(note);
dispatch(NoteActions.addNote(note));
}}
/>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
width: '100%',
margin: 10,
},
textInput: {
width: '100%',
marginBottom: 10,
textAlign: 'center',
borderBottomWidth: 1,
},
});
export default NoteScreen;
And below is the action js file.
// action types
export const ADD_NOTE = 'ADD_NOTE'
//action creators
export function addNote(note){
return{
type:ADD_NOTE,
date:note
}
}
And below is the reducer js file
// initial state
const initialState ={
noteList:[]
}
// import actions
import ADD_NOTE from '../actions/Note';
function noteReducer (state=initialState, action){
debugger;
switch(action.type){
case ADD_NOTE:
const newNote = action.data
return{
...state,
noteList: state.noteList, newNote
}
default:
return state;
}
}
export default noteReducer;
Please help me.
Thanks in advance,
Yohan
You need to add layer of dispatch at your action, also watch the typo date instead data
export const addNote = (note) => (dispatch, getState) => {
return dispatch({
type:ADD_NOTE,
data :note
})
}

Choose firestore subcollection when connecting component to redux with react-redux-firebase

I am using react-redux-firebase's fireStoreConnect() middleware with
a screen in my react-native mobile app. At the time of connecting the component to the redux store, I want to specify the firestore sub-collection I connect to, which depends on the user that is navigating the app.
How should I specify the collection in firestoreConnect? The user id is in the redux store.
MWE:
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { compose } from 'redux';
import { connect } from 'react-redux'
import { firestoreConnect } from 'react-redux-firebase';
class PhotosScreen extends Component {
render() {
return (
<View>
<Text> i plan the use this.props.images here </Text>
</View>
);
}
}
const mapStateToProps = (state) => {
// reference the subcollection of the user
const images = state.firestore.data.images;
return {
images: images,
}
}
export default compose(
firestoreConnect([
{
collection: 'users',
doc: "HOW DO I GET THE USERS ID HERE? IT IS IN REDUX STORE",
subcollections: [{ collection: 'images' }]
}
]),
connect(mapStateToProps),
)(PhotosScreen)
Firestore (and all NoSQL databases) follow an alternating "(parent) collection / document / collection / document ..." hierarchical pattern. To synchronize a React component to subcollections and documents below the parent firestore collection, you need to pass the subcollection/subdocument hierarchy information as props to firestoreConnect.
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { compose } from 'redux';
import { connect } from 'react-redux'
import { firestoreConnect } from 'react-redux-firebase';
class PhotosScreen extends Component {
render() {
return (
<View>
<Text> i plan the use this.props.images here </Text>
{images && images.length ? <div> render your images here using this.props.images and images.map </div> : <p>No images</p>}
</View>
);
}
}
const mapStateToProps = (state) => {
return {
images : state.firestore.data.images, // reference the subcollection of the user
userId : state.firestore.auth.uid // assuming the 'doc id' is the same as the user's uid
}
}
export default compose(
firestoreConnect((props) =>
if (!props.userId) return [] // sync only if the userId is available (in this case, if they are authenticated)
return [
{
collection : 'users', // parent collection
doc : props.userId, // sub-document
subcollections : [
{collection : 'images'} // sub-collection
],
storeAs : 'images'
}
]
}),
connect(mapStateToProps),
)(PhotosScreen)
In 1.x
const enhance = compose(
connect(
(state) => ({
someKey: state.someData
})
),
firebaseConnect(
(props, firebaseInstance) => [
{ path: `${props.someKey}/someData` }
]
)
)
In 2.x
firebaseConnect(
(props, store) => [
{ path: `${store.getState().someKey}/someData` }
]
)
Note how the 2nd argument in firebaseConnect changes from firebaseInstance to store from v1 to v2.
This should get you what you need.

How to Debug White Screen Page (No Content Showing) in RN Expo App with No Error Prompts

I've been building an app in React Native Expo. First, I incorporated Facebook Login simply by copying and pasting the login async code into Login.js and added this.login() to componentWillMount. This worked - With the Facebook login popup showing up as app loads. I was able to log into my FB account with a success message.
However, as soon as I tried to incorporate Firebase, particularly somewhere between transferring code between my Home.js page and the Login.js page, I started getting this white screen to appear on page load.
There are no errors in a terminal; except a message that FacebookAppID and facebookDisplayName do not belong in app.json.
I tried adding a different background color (black) in CSS, which works, but still, there is no content.
Removing FacebookAppID and facebookDisplayName from app.json, which did nothing.
Updating my App Key to the correct one (I was missing the last number).
Restarted the terminal, expo web terminal x code and metro builder several times.
Updated my code so that every file in my Screens directory has { connect } & { login } imports as well as functionMapStateToProps and export default connect statements at bottom.
I tried changing a tab in TabNavigator.js to Login page, and using "Login" as the initialRouteName, but got an error that Login.js isn't a React component.
The first page that should show up before any other is the Facebook login...So it would seem the issue is there.
App.js
import React from 'react';
import Login from './screens/Login';
import reducers from './redux/reducers';
import thunkMiddleware from 'redux-thunk';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
const middleware = applyMiddleware(thunkMiddleware);
const store = createStore(reducers, middleware);
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<Login/>
</Provider>
);
}
}
------ end of App.js ------------
Login.js
import React from 'react';
import styles from '../styles'
import RootNavigator from '../navigation/RootNavigator';
import { connect } from 'react-redux';
import { login } from '../redux/actions';
import * as firebase from 'firebase';
import firebaseConfig from '../config/firebase.js';
firebase.initializeApp(firebaseConfig)
import {
Text,
View,
TouchableOpacity
} from 'react-native';
class Login extends React.Component
state = {}
componentWillMount() {
firebase.auth().onAuthStateChanged((user) => {
if (user != null) {
this.props.dispatch(login(true))
console.log("We are authenticated now!" + JSON.stringify(user));
}
});
}
login = async () => {
const { type, token } = await Expo.Facebook.logInWithReadPermissionsAsync('YourAppKeyGoesHere', {
permissions: ['public_profile'],
});
if (type === 'success') {
// Build Firebase credential with the Facebook access token.
const credential = await firebase.auth.FacebookAuthProvider.credential(token);
// Sign in with credential from the Facebook user.
firebase.auth().signInWithCredential(credential).catch((error) => {
// Handle Errors here.
Alert.alert("Try Again")
});
}
}
render() {
if(this.props.loggedIn){
return (
<RootNavigator/>
)
} else {
return (
<View style={styles.container}>
<TouchableOpacity onPress={this.login.bind(this)}>
<Text>{this.props.loggedIn}</Text>
</TouchableOpacity>
</View>
)
}
}
}
function mapStateToProps(state) {
return {
loggedIn: state.loggedIn
};
}
export default connect(mapStateToProps)(Login);
---------end of Login.js ----------
Home.js
import React from 'react';
import styles from '../styles';
import { connect } from 'react-redux';
import { login } from '../redux/actions';
import {
Text,
View,
Alert
} from 'react-native';
class Home extends React.Component {
state = {}
componentWillMount() {
}
render() {
return (
<View>
<Text>Home</Text>
</View>
)
}
}
function mapStateToProps(state) {
return {
loggedIn: state.loggedIn
};
}
export default connect(mapStateToProps)(Home);
-----end of Home.js ------
redux folder
actions.js
export function login(){
return function(dispatch){
dispatch({ type: 'LOGIN', payload: input });
}
}
----end of actions.js ----
reducers.js
export default reducers = (state = {
loggedIn: false,
}, action) => {
switch (action.type) {
case 'LOGIN': {
return { ...state, loggedIn: action.payload }
}
}
return state;
}
------end of reducers.js ------
-----end of redux folder ------
-----navigation folder (react navigation) -------
---RootNavigator.js---
import React from 'react';
import TabNavigator from './TabNavigator';
import {
createDrawerNavigator,
createStackNavigator,
createBottomTabNavigator,
createAppContainer,
} from 'react-navigation';
const AppNavigator = createStackNavigator(
{
Main: {
screen: TabNavigator,
},
}
);
const AppContainer = createAppContainer(AppNavigator);
export default class RootNavigator extends React.Component {
render() {
return <AppContainer/>;
}
}
----end of RootNavigator.js-----
----TabNavigator.js----
import React from 'react';
import Home from '../screens/Home';
import Profile from '../screens/Profile';
import Matches from '../screens/Matches';
import {
createDrawerNavigator,
createStackNavigator,
createBottomTabNavigator,
createAppContainer,
createMaterialTopTabNavigator,
} from 'react-navigation';
export default createBottomTabNavigator(
{
Profile: {
screen: Profile,
navigationOptions: {
tabBarLabel: 'Profile',
},
},
Home: {
screen: Home,
navigationOptions: {
tabBarLabel: 'Home',
}
},
Matches: {
screen: Matches,
navigationOptions: {
tabBarLabel: 'Matches',
},
},
},
{
navigationOptions: {
header: null
},
tabBarPosition: 'top',
initialRouteName: 'Home',
animationEnabled: true,
swipeEnabled: true,
tabBarOptions: {
style: {
height: 75,
backgroundColor: 'blue'
},
}
}
);
-----end of TabNavigator----
Have you tried remote js Debugging?
What you can do is, Debugg JS remotely.
https://developers.google.com/web/tools/chrome-devtools/remote-debugging/
try to console.log("hi"); when your first component of your app mounts.
Try to add it in login page when the login component mounts.
That will help you debug unseen error which gets listed in the js debugger.
Just check those errors and follow up!
You're good to go!
I was also getting splash logo white screen, tired possible solution nothing works out, at last I have remove node_module and yarn.lock. then reinstall and update expo
follows cmd:-
$ npm install
$ yarn add expo
$ expo update
try this , works for me.
!!enjoy!!
As the other answer suggests, once you've done console.log to see the component is actually loading, then for me the issue was I couldn't actually see the content.
My solution was to wrap my content with a <View> to align the content in the middle of the page.
I understand your question is more complex than that, but hopefully, my answer might be able to help other people.
<View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'space-around',
}}>
<Text>Can you see this?</Text>
</View>
in my case,
style = {{ borderColor : #fff }}
my mistake is exceptin ' at borderColor value...
fix change to
style = {{ borderColor : '#fff' }}
Some components such as useState was imported from wrong url, I changed it and imported it from react and fixed it

Resources