What's wrong with my Fire Base code (React Native) - javascript

Trying to set up some testdata in React Native using Firebase. I have successfully installed using $yarn add firebase. I have added test data in FB like this:
FB data
And in my project I added the following code:
import * as firebase from 'firebase'
const firebaseConfig = {
apiKey: "AIzaSyBNKM6Ptbynkg5dEJkwMHNsZhUCsW2JqGE",
authDomain: "testproject-f4c9f.firebaseapp.com",
databaseURL: "https://testproject-f4c9f.firebaseio.com",
projectId: "testproject-f4c9f",
storageBucket: "testproject-f4c9f.appspot.com",
messagingSenderId: "48530616964"
}
firebase.initializeApp(firebaseConfig)
Then in the rendering:
let mytext = ""
let testing =
firebase.database().ref('testCategory/test1/FirstHeader');
testing.on('value', function(snapshot) {
mytext = snapshot.val()
});
return(
<View>
<Text>{mytext}</Text>
</View>
);
Running the app, nothing shows. Any ideas would be appreciated.
UPDATE:
I managed to get it right in the console.log with this code:
let child = ""
var ref = firebase.database().ref("testCategory");
ref.once("value")
.then(function(snapshot) {
child = snapshot.child("test1/testHeader").val()
console.log({child})
});
But for some reason I can't print it in the text output:
return(
<View>
<Text>{this.child}</Text>
</View>
);
It's just blank...

You need to pass the data from the callback to the view. You should use a state manager like Redux or MobX, but for this example, you can just use the component state.
This is what your component should look like.
class Hello extends Component {
state = {
child: ''
}
componentDidMount() {
firebase
.database()
.ref('testCategory')
.on('value')
.then(snapshot => {
const child = snapshot.child('test1/testHeader').val()
this.setState({
child
})
})
}
render() {
const { child } = this.state
return (
<View>
<Text>{child}</Text>
</View>
)
}
}
Tada!

Related

Can't get all document from collection firebase firestore

I don't understand why I can't get data from firebase firestore database.
my error :
[FirebaseError: Expected first argument to collection() to be a CollectionReference, a DocumentReference or FirebaseFirestore]
My config file with firebase config is correctly set, I can add Data with this model :
{ item: { ...event, date } }
My files structures : picture of my structure
I have correctly declared my state, I have async await with try catch.
I have used this from firebase documentation
EventList.js
import { FlatList, View, Text, StyleSheet } from "react-native";
import React, { useState, useEffect } from "react";
import { EVENTS_COLLECTION } from "../commons/constants";
import db from "../commons/services/firebase";
const EventList = () => {
const [events, setEvents] = useState([]);
return (
<View>
<FlatList
data={events}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<View style={styles.eventContainer}>
<Text style={styles.eventName}>{item.name}</Text>
<Text style={styles.eventDate}>{item.date.toString()}</Text>
</View>
)}
/>
</View>
);
};
firebase.Js
const firebaseConfig = {
apiKey: "",
authDomain: "",
databaseURL:
"",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: "",
};
const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
I try to get all documents from my events collection.
My goal is to make an Calendar with event manager with firebase firestore database
In firebase.js you export db like this:
export const db = getFirestore(app);
This is a named export, therefore you will need a named import:
import { db } from '../commons/services/firebase'
// or
// import * as config from '../commons/services/firebase'
// const db = config.db
The way you import is for default exports and results in your case with undefined. Therefore firebase complains that the first argument to collection is not correct (it's undefined).
You can read more about imports here.
Try this one if EVENTS_COLLECTION returns the name of the collection correctly then you will get all documents otherwise use "Collection Name" where you write EVENTS_COLLECTION.
const fetchEvents= async () => {
await db.collection(EVENTS_COLLECTION).onSnapshot({
error: e => console.error(e),
next: (querySnapshot) => {
var data = [];
var i = 0;
querySnapshot.forEach(doc => {
data.push(doc.data());
console.log(doc.id, " => ", doc.data());
});
setEvents(data)
},
})
};

React Hook useEffect multiple problems

This is my first time using a useEffect hook. what its doing is reading the database to see if a value returns and if a value returns thats the userToken which is sign of an account so it signs you in. However, I have 2 problems. The Link name button doesnt automatically sign you in, instead you have to type another letter in the input box after to sign in. I tried fixing this by adding connectUser under writeUserData on line 49 but that just makes the site crash. My second problem is I cant display {userToken} on the page after bewing signed in. I recieve Error: Objects are not valid as a React child (found: object with keys {username}). If you meant to render a collection of children, use an array instead.
import React, { useState, useEffect } from "react";
import {initializeApp} from 'firebase/app';
import { getDatabase, ref, set, child, get} from 'firebase/database';
export default function Username(props) {
const [userName, setUsername] = useState('');
const [userToken, setuserToken] = useState('')
const clientCredentials = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
}
const app = initializeApp(clientCredentials);
const db = getDatabase();
const address = props.address;
function writeUserData(userId, userN, ) {
const reference = ref(db, 'users/' + userId);
set(reference, {
username: userN,
});
}
const dbRef = ref(getDatabase());
function connectUser() {
get(child(dbRef, `users/${address}`)).then((snapshot) => {
if (snapshot.exists()) {
setuserToken(snapshot.val());
} else {
console.log("No data available");
}
}).catch((error) => {
console.error(error);
});
}
const handleChange = (event) => setUsername(event.target.value);
function handleClick(e) {
writeUserData( address, userName);
}
useEffect(() => {
connectUser()
});
while (userToken == '')
return (
<>
<div>
<p className = "account-Info" >address: {address}</p>
</div>
<div id="form">
<h2 className='user-Create' > Username </h2>
<form id='set-User'>
<input id='username' className="user-Create" type='text' value={userName} onChange={handleChange}
required minLength='3' maxLength='30' pattern="[a-zA-Z0-9_]+" title='only letters, numbers, and underscores.'/>
<button className='user-Create' type="button" onClick={handleClick}>Link Name</button>
</form>
</div>
</>
);
while (userToken)
return (
<p className = "account-Info" >hi user</p>
);
}
First, please do not use while. Instead, use if.
if (!Boolean(userToken)) return <something />;
// No need to give condition here
// If userToken is not false, this will return
return <main />;
Second, useEffect's dependency, according to what you wrote, which is
useEffect(() => {
connectUser();
});
It means you execute connectUser() everytime any component update. Pass a dependency. If want no dependency, use [], which means execute connectUser() only once when component mounts.
useEffect(() => {
connectUser();
},[]);
Third, for Error: Objects are not valid as a React child (found: object with keys {username}), if you get similar error in future, use console.log() to debug. In your case, console.log(userToken) and go see in console of your browser.
Fourth, if you are handling about authentication, did you consider using firebase/auth?
For useEffect running multiple times, please pass in a dependency array. Check the react documentation on useEffect. You can start by giving an empty array as the second parameter to useEffect

why it is returning null?

Hi I am trying to learn firebase. Now I am trying to follow what is inside the github doc.
Like to gitHub
This is my index.js file
const rfConfig = {}; // optional redux-firestore Config Options
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: 'something',
authDomain: 'something',
databaseURL: 'something',
projectId: 'something',
storageBucket: 'something.com',
messagingSenderId: 'something',
appId: '1:something',
measurementId: 'G-something',
};
firebase.initializeApp(firebaseConfig);
// Initialize Cloud Firestore through Firebase
firebase.firestore();
// Add reduxFirestore store enhancer to store creator
const createStoreWithFirebase = compose(
reduxFirestore(firebase, rfConfig), // firebase instance as first argument, rfConfig as optional second
)(createStore);
// Add Firebase to reducers
const rootReducer = combineReducers({
firestore: firestoreReducer,
});
// Create store with reducers and initial state
const initialState = {};
const store = createStoreWithFirebase(rootReducer, initialState);
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
My folder got 3 components. 1 is for adding todo. 1 is for displaying todo. & the last 1 is combination of the first two
Here is my app component & TodoShow Component
const App = () => {
return (
<div>
<TodoShow/>
</div>
)
}
const TodoShow = () => {
return (
<div>
<Todo/>
{/* <Todos/> */}
</div>
)
}
Inside the Todo button component I want to add a new todo when i click on a button
import { useFirebase } from 'react-redux-firebase'
export default function Todo() {
const firebase = useFirebase()
function addSampleTodo() {
const sampleTodo = { text: 'Sample', done: false }
return firebase.push('todos', sampleTodo)
}
return (
<div>
<h1>New Sample Todo</h1>
<button onClick={addSampleTodo}>Add</button>
</div>
)
}
But when I click on the button, The app doesn't know firebase.
Here is the photo
Is there something i am missing here? I have already install firebase,react-redux-firebase,redux-firestore
You need to render a ReactReduxFirebaseProvider near the top of your component tree. This is what useFirebase is trying to access, so without one, you get undefined.
const rrfConfig = {
userProfile: 'users'
// useFirestoreForProfile: true // Firestore for Profile instead of Realtime DB
}
const rrfProps = {
firebase,
config: rrfConfig,
dispatch: store.dispatch
// createFirestoreInstance // <- needed if using firestore
}
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<ReactReduxFirebaseProvider {...rrfProps}>
<App />
</ReactReduxFirebaseProvider>
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
For more info see this section of the documentation: https://github.com/prescottprue/react-redux-firebase#use

React Native: No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app/no-app)

I am trying to implement persistent login for my application. I am facing error
No Firebase App '[DEFAULT]' has been created - call Firebase App.initializeApp() (app/no-app)
I tried solving it by looking into the existing issues but does not quite fit into this use case.
I have initialised my firebase from App.js and then after navigating to SplashScreen (AuthStack based on a state) I am calling an action creator from ComponentDidMount inside of SplashScreen. In that action creator I am checking the Auth State(if user returns non null then I am updating the state to move to AppStack).
App.js
class App extends Component {
componentDidMount() {
const firebaseConfig = {
apiKey: 'AIzaSyDOpO3TjIN4lCCufMZWKs7eZYd86SJB0o8',
authDomain: 'vocabs-a3f7e.firebaseapp.com',
databaseURL: 'https://vocabs-a3f7e.firebaseio.com',
projectId: 'vocabs-a3f7e',
storageBucket: 'vocabs-a3f7e.appspot.com',
messagingSenderId: '938659592890',
appId: '1:938659592890:web:7d309f3751892982066083',
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
}
render() {
return (
<Provider store={createStore(reducers, {}, applyMiddleware(ReduxThunk))}>
<NavigationContainer>
<MainRoute />
</NavigationContainer>
</Provider>
);
}
Splash screen
class SplashScreen extends Component {
componentDidMount() {
setTimeout(this.renderSignInForm, 1000);
//this.renderSignInForm();
}
renderSignInForm = () => {
console.log('inside async');
this.props.persistantSignIn();
//const userData = this.checkUser();
if (this.props.userData) {
console.log('hit user true' + this.props.userData);
} else {
// No user is signed in.
console.log('hit user false' + this.props.userData);
this.props.navigation.navigate('SignInForm');
}
};
render(){
return(
/*some Code Here*/
);
}
ActionCreator
export const persistantSignIn = () => {
return (dispatch) => {
firebase
.auth()
.onAuthStateChanged.then((userData) => {
console.log(userData);
dispatch({
type: PERSISTANT_SIGN_IN,
payload: userData,
});
})
.catch((error) => {
console.log('something is wronggggggggg');
throw error;
});
};
};
MainRoute.js
class MainRoute extends Component {
render() {
return this.props.isSignedIn ? <AppStack /> : <AuthStack />;
}
}

How to fix 'undefined is not an object' error in react native

I am attempting to move my react-native app code to be in a more structured manner. Originally, I had all of my firebase functions inside the file where I used them, but now I would like to use them in multiple places, so I created a Database.js file with a Database class and all of the functions. For some reason though, whenever I try to use one of the functions from the new class, I get the error "undefined is not an object (evaluating 'this.codesRef.once')" Please help!
So far, I have tried using arrow functions, a constructor, and importing firebase in different ways, all to no avail. I am pretty much stumped on this one.
Have a look at the code...
(/project/src/components/forms/KeyForm.js)
import React from 'react';
import { StyleSheet, View, TextInput } from 'react-native';
import db from '../Database.js';
class LoginForm extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<View style={styles.container}>
<TextInput
placeholder="Access Code"
returnKeyType="go"
onSubmitEditing={text => {db.checkCode(text.nativeEvent.text)}}
/>
</View>
);
}
}
const styles = StyleSheet.create({ // stylesheet
// yay styles :)
});
export default LoginForm;
(/project/src/components/Database.js)
//import * as firebase from "firebase";
var firebase = require('firebase');
if (!firebase.apps.length) {
firebase.initializeApp({
apiKey: "key",
authDomain: "domain",
databaseURL: "url",
storageBucket: "bucket",
});
}
class Database {
codesRef = firebase.database().ref('codes');
static checkCode(text) {
let codeIsFound = false;
this.codesRef.once('value', (db_snapshot) => { // this won't work
db_snapshot.forEach((code_snapshot) => {
if (text == code_snapshot.val().value) {
codeIsFound = true;
identifier = code_snapshot.key;
}
});
});
if (codeIsFound) {
//this.deleteCode(identifier);
console.log("code found");
this.props.navigation.navigate('Create'); // side-question => how can i get this working in Database.js? Do i need to use withNavigation?
} else {
console.log("code not found");
);
}
};
}
module.exports = Database;
Just to clarify, everything worked 100% fine until i tried to migrate the functions to the Database.js file. Any help is greatly appreciated!
Your checkCode function is static. You cannot access this context inside static methods.
in your /project/src/components/Database.js Change it like this:
checkCode(text) {
let codeIsFound = false;
this.codesRef.once('value', (db_snapshot) => { // this won't work
db_snapshot.forEach((code_snapshot) => {
if (text == code_snapshot.val().value) {
codeIsFound = true;
identifier = code_snapshot.key;
}
});
});
if (codeIsFound) {
//this.deleteCode(identifier);
console.log("code found");
this.props.navigation.navigate('Create'); // side-question => how can i get this working in Database.js? Do i need to use withNavigation?
} else {
console.log("code not found");
);
}
};
When accessing this function inside /project/src/components/forms/KeyForm.js
import firbaseDB from '../Database.js';
const db = new firbaseDB();
...
Rest of your code as it is. Cheers.
Try having a constructor in your class:
class Database {
constructor() {
this.codesRef = firebase.database().ref("codes");
}
//...
}
Maybe you have to do it this way
class Database {
constructor(props) {
super(props);
this.codesRef = firebase.database().ref("codes");
}
//...
}

Categories