I am learning how to implement Firestore with react-native(Android). Then, I found 'react-native-firebase' and stuck in this exception.
Error:Exception in
HostObject::get(propName:RNFirebase):
java.lang.NoClassDefFoundError: Failed resolution
of: Lcom/google/firebase/FirebaseApp;
I already setup firebase in my gradle (ref.https://firebase.google.com/docs/android/setup/?authuser=0)
Firebase database's rule
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write;
}
}
}
and this is my learning code (ref.https://www.youtube.com/watch?v=_GOI7h9ojr8)
import React,{ Component } from 'react';
import {
Flatlist,
Text,
TextInput,
TouchableHighlight,
Image,
View } from 'react-native';
import firebase from 'react-native-firebase';
export default class test extends Component {
constructor(props){
super(props);
this.state = ({
todoTask: [],
newTaskName: '',
loading: false
});
this.ref = firebase.firestore().collection('todo');
}
onPressAdd = () => {
this.ref.add({
taskName: this.state.newTaskName
}).then((data) => {
console.log('added data = ${data}');
this.setState({
newTaskName: '',
loading: true
});
}).catch((error) => {
console.log('error adding firestore document = ${error}');
this.setState({
newTaskName: '',
loading: true
});
});
}
render(){
return (
<View style={{flex: 1}}>
<Text>Hello</Text>
<TextInput style={{
height: 40,
width: 200,
margin: 10,
padding: 10,
borderColor: 'white',
borderWidth: 1,
color: 'white'
}}
keyboardType='default'
placeholderTextColor='white'
placeholder='Enter task name'
onChangeText={
(text) => {
this.setState({ newTaskName: text});
}
}
>
</TextInput>
<TouchableHighlight
style={{ marginRight: 10 }}
underlayColor='tomato'
onPress={this.onPressAdd}>
<Image
style={{ width: 35, height: 35 }}
source={require('./icon-add.png')}
>
</Image>
</TouchableHighlight>
<Flatlist
data={this.state.todoTask}
renderItem={({item, index}) => {
return(
<Text>{item.taskName}</Text>
);
}}
>
</Flatlist>
</View>
);
}
}
Can u explain why it happen? Thanks a lot.
You installed 'react-native-firebase' package so kindly note to remove(uninstall) it.
According to the docs:
First you need to install firebase package:
npm install --save firebase
Then import it using firebase/app:
// Firebase App (the core Firebase SDK) is always required and
// must be listed before other Firebase SDKs
import * as firebase from "firebase/app";
Also making sure you have the library you are using in your android/app/build.gradle in my case firebase-core
implementation "com.google.firebase:firebase-core:17.4.3"
Related
Making an instagram clone and it won't let me post a picture. I keep getting this error 'Uncaught Error in snapshot listener:, [FirebaseError: Missing or insufficient permissions.]' whenever I enter the page to upload a picture. My guess is that it's coming from the onSnapshot function. I also get the 'Warning: An unhandled error was caught from submitForm(), [TypeError: null is not an object (evaluating 'currentLoggedInUser.username')]' when I press the share button. Nothing happens beyond that point. Its supposed to take me back to the homescreen afterwards:
import { View, Text, Image, TextInput, Button } from 'react-native'
import React, { useState, useEffect } from 'react'
import * as Yup from 'yup'
import { Formik } from 'formik'
import { Divider } from 'react-native-elements'
import validUrl from 'valid-url'
import {db, firebase} from '../../firebase'
const PLACEHOLDER_IMG = 'https://pacificpatiostructures.com/wp-content/uploads/2016/06/import_placeholder.png'
const uploadPostSchema = Yup.object().shape({
imageUrl: Yup.string().url().required('A URL is required'),
caption: Yup.string().max(2200, 'Caption has reached the character limit.')
})
const FormikPostUploader = ({ navigation }) => {
const [thumbnailUrl, setThumbnailUrl] = useState(PLACEHOLDER_IMG)
const [currentLoggedInUser, setCurrentLoggedInUser] = useState(null)
const getUsername = () => {
const user = firebase.auth().currentUser
const unsubscribe = db
.collection('user')
.where('owner_uid', '==', 'user.uid').limit(1).onSnapshot(
snapshot => snapshot.docs.map(doc => {
setCurrentLoggedInUser({
username: doc.data().username,
profilePicture: doc.data().profile_picture,
})
})
)
return unsubscribe
}
useEffect(() => {
getUsername()
}, [])
const uploadPostToFirebase = (imageUrl, caption) => {
const unsubscribe = db
.collection('users')
.doc(firebase.auth().currentUser.email).collection('posts')
.add({
imageUrl: imageUrl,
user: currentLoggedInUser.username,
profile_picture: currentLoggedInUser.profilePicture,
owner_uid: firebase.auth().currentUser.uid,
caption: caption,
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
likes: 0,
likes_by_users: [],
comments: [],
})
.then(() => navigation.goBack())
return unsubscribe
}
return (
<Formik
initialValues={{caption: '', imageUrl: ''}}
onSubmit={values => {
uploadPostToFirebase(values.imageUrl, values.caption)
}}
validationSchema={uploadPostSchema}
validateOnMount={true}
>
{({
handleBlur,
handleChange,
handleSubmit,
values,
errors,
isValid
}) => (
<>
<View
style={{
margin: 20,
justifyContent: 'space-between',
flexDirection: 'row',
}}>
<Image source={{ uri: validUrl.isUri(thumbnailUrl) ? thumbnailUrl : PLACEHOLDER_IMG}}
style={{ width: 100, height: 100 }}/>
<View style={{ flex: 1, marginLeft: 12 }}>
<TextInput
style={{ color: 'white', fontSize: 20 }}
placeholder='Write a caption...'
placeholderTextColor='gray'
multiline={true}
onChangeText={handleChange('caption')}
onBlur={handleBlur('caption')}
value={values.caption}
/>
</View>
</View>
<Divider width = {0.2} orientation='vertical' />
<TextInput
onChange={(e) => setThumbnailUrl(e.nativeEvent.text)}
style={{ color: 'white', fontSize: 18 }}
placeholder='Enter Image Url'
placeholderTextColor='gray'
onChangeText={handleChange('imageUrl')}
onBlur={handleBlur('imageUrl')}
value={values.imageUrl}
/>
{errors.imageUrl &&(
<Text style={{ fontSize: 10, color: 'red' }}>
{errors.imageUrl}
</Text>
)}
<Button onPress={handleSubmit} title='Share' disabled={!isValid}/>
</>
)}
</Formik>
)
}
export default FormikPostUploader
Here are my security rules that I used in Cloud Firestore:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function userIsAuthenticated() {
return request.auth != null;
}
// security rule for group collection ('post')
match /{path=**}/posts/{postId} {
allow read, write: if userIsAuthenticated();
}
match /users/{userId} {
allow read, write: if userIsAuthenticated();
}
}
}
Your getUsername() function queries user collection which is not included in your Firestore Rules which returns Missing or insufficient permissions.
As per this documentation:
Cloud Firestore security rules evaluate each query against its potential result and fails the request if it could return a document that the client does not have permission to read. Queries must follow the constraints set by your security rules.
You should also add necessary permissions to the user collection. See sample rule below:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function userIsAuthenticated() {
return request.auth != null;
}
// security rule for group collection ('post')
match /{path=**}/posts/{postId} {
allow read, write: if userIsAuthenticated();
}
match /users/{usersId} {
allow read, write: if userIsAuthenticated();
}
// Security Rule for `user` collection.
match /user/{userId} {
allow read, write: if userIsAuthenticated();
}
}
}
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
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
});
}
I'm creating a react native app. now I want to view my App database tables.
I don't know how many tables are in my SQLite database.
I am new in react native development & SQLite please help. to solve this issue
You can solve this problem through the Table View command. It can also be used to view data for that table.
/*Screen to view all the table*/
import React from 'react';
import { FlatList, Text, View } from 'react-native';
import { openDatabase } from 'react-native-sqlite-storage';
var db = openDatabase({ name: 'UserDatabase.db' });
export default class ViewAllTable extends React.Component {
constructor(props) {
super(props);
this.state = {
FlatListItems: [],
};
db.transaction(tx => {
tx.executeSql('SHOW TABLES', [], (tx, results) => {
var temp = [];
for (let i = 0; i < results.rows.length; ++i) {
temp.push(results.rows.item(i));
}
this.setState({
FlatListItems: temp,
});
});
});
}
ListViewItemSeparator = () => {
return (
<View style={{ height: 0.2, width: '100%', backgroundColor: '#808080' }} />
);
};
render() {
return (
<View>
<FlatList
data={this.state.FlatListItems}
ItemSeparatorComponent={this.ListViewItemSeparator}
keyExtractor={(item, index) => index.toString()}
renderItem={({item, index }) => (
<View key={item[index]} style={{ backgroundColor: 'white', padding: 20 }}>
<Text>Table: {item[index]}</Text>
</View>
)}
/>
</View>
);
}
}
What I'm trying to do here is to actually just read data from my firestore. I followed all the installation from RNF's docs, but when I try to get data from my documents or just reference into firestore collection, an error shows up:
I tried changing the rules (as I thought it was the rules involved) but no luck.
Here is my database structure:
And below are my codes :
import React, { Component } from 'react';
import {View, Text, FlatList, Image, StyleSheet, Button, TouchableHighlight} from 'react-native';
import firebase from 'react-native-firebase';
import MainApp from './src/screen/test';
export default class App extends Component<{}> {
constructor(){
super();
this.itemsRef = this.getRef('questions');
this.state = {
items:[],
loading:true,
};
}
setModalVisible(visible){
this.setState(modalVisible:visible);
}
getRef(location){
return firebase.firestore().collection('chat');
}
componentWillMount(){
this.getItems(this.itemsRef);
}
componentDidMount(){
//this.getItems(this.itemsRef);
}
getItems(itemsRef){
firebase.firestore().collection('Users').get().then((snap)=>{
let items =[];
alert(snap);
snap.forEach((childSnap)=>{
items.push({
title:childSnap.val().question,
_key:childSnap.key
});
alert(childSnap.key)
})
this.setState({
items,
loading:false
})
})
}
pressRow(item){
alert(item);
}
renderRow(item){
return(
<TouchableHighLight onPress={()=>{
this.pressRow(item)
}}>
<View>
<Text>{item.title}</Text>
</View>
</TouchableHighLight>
)
}
addItem(){
}
render() {
if (this.state.loading) {
return null; // or render a loading icon
}
return (
<View style={{ flex: 1 }}>
<FlatList
data={this.state.items}
/>
<Button
title={'Add TODO'}
onPress={() => console.log()}
/>
</View>
);
}
}
How can I fix this error?
The default setting for firestore is to disable access.
So if you don't have your access rules set up, you can't fetch data.
Change them to this - but ONLY for testing:
service cloud.firestore {
match /databases/{database}/documents {
// Match all documents, recursively, with a wildcard and the "=**" recursive modifier
match /{document=**} {
allow read, write;
}
}
}
Then after it works - read more about here.