push to new page within function react - javascript

I'm new to react, and I am trying to push to a new page through a function. The function is createCheckoutSession... here's what I have.
export async function createCheckoutSession(activtyStatus){
let user = firebase.auth().currentUser;
if (user == null) {
this.props.history.push(routes.CLIENTS)
}
how to I declare this.props, or how do I actually push the new page? It is logging error:
'props' is not defined no-undef
here is my entire page.
import { loadStripe } from '#stripe/stripe-js';
import firebase from 'firebase';
import "firebase/auth";
import * as routes from '../routes';
import './checkout.css';
import React, { useState, useEffect } from "react";
import MyGifSpinner from './manageSubSpinner';
import './manageSubSpinner.css';
import ReactDOM from 'react-dom';
import myGif from '../pages/spinner';
import myGifSpinner from './manageSubSpinner';
import { doSignOut } from '../models/AuthorizationHome';
const firestore = firebase.firestore();
const app = firebase.app();
export async function createCheckoutSession(activtyStatus){
let user = firebase.auth().currentUser;
if (user == null) {
this.props.history.push(routes.CLIENTS)
}
console.log(user)
//price ID with trial LIVE ID
var price = 'price_1IGW85KDPaWWeL1yjWsi9oRa'
// var price = 'price_1Iav0JKDPaWWeL1yBa9F7Aht'
firestore.collection('customers').doc(user.uid).collection('subscriptions').get().
if (activtyStatus == "canceled") {
console.log("sub is cancelled")
//live price
price = 'price_1IfmDsKDPaWWeL1ywjMTGarh'
}
console.log("activity status is: " + activtyStatus)
const checkoutSessionRef = await firestore
.collection('customers')
.doc(user.uid)
.collection('checkout_sessions')
.add({
price: price,
success_url: "http://localhost:3000/clients",
cancel_url: "http://localhost:3000/signin",
});
// Wait for the CheckoutSession to get attached by the extension
checkoutSessionRef.onSnapshot(function (snap) {
const { error, sessionId } = snap.data();
if (error) {
console.log(`An error occured: ${error.message}`);
return;
}
if (sessionId) {
const stripe = window.Stripe('pk');
console.log("going to stripe: ")
// this.setState({ isRegistering: true });
console.log("line 116 checkout.js")
stripe.redirectToCheckout({sessionId: sessionId})
console.log("logged stripe")
}
});
}
it is basically a function to call stripe, and open the stripe checkout page in the new window. So I am trying to catch if the user == null, and if true, the push them to sign in page

As I have already said, you cant use this in a React function since it is stateless, so you need to useHistory. So you need to this to your code
import { useHistory } from "react-router-dom";
export async function createCheckoutSession(activtyStatus){
let history = useHistory();
let user = firebase.auth().currentUser;
if (user == null) {
history.push(routes.CLIENTS)
}
...

Related

React Native and FIrebase: Making an async call seems to run through twice

as I continue to work on my issues I've got one that's kind of perplexing. my app has two JS files that interact with each other, but what's odd is it seems that then I call the function to get the data from firestore it seems that it wants to run it twice.
Here is the HomeScreen.js file that is suppoed to call UserInformation
import { Pressable, Text } from 'react-native';
import { useEffect, useId, useState } from 'react';
import { async } from '#firebase/util';
import { FlatList } from 'react-native-gesture-handler';
import {getStorage, ref, getDownloadURL} from 'firebase/storage';
//import the user infomration component
import UserInformation from '../components/UserInformation';
import ClubInformation from '../components/ClubInformation';
import AircraftInformation from '../components/AircraftInformation';
function HomeScreen() {
const userDetails = UserInformation();
const clubDetails = ClubInformation();
const aircraftDetails = AircraftInformation();
if (userDetails !== null) {
//console.log(userDetails)
//console.log(clubDetails)
//console.log(aircraftDetails)
}
if(!userDetails) {
return <Text>Loading...</Text>
}
if(!clubDetails) {
return <Text>Loading...</Text>
}
return <Text>Welcome {userDetails.first} {userDetails.last} {clubDetails.name}! This is a placeholder for future updates in the home screen</Text>
}
export default HomeScreen
the userDetails calls is below:
userInformation.js
import { useState, useEffect } from "react";
import { getAuth } from "firebase/auth";
import { doc, getDoc } from "firebase/firestore";
import { db } from '../components/FirebaseConfig';
export default function UserInformation() {
const [userDetails, setUserDetails] = useState(null);
useEffect(() => {
async function getUserDetails() {
const user = getAuth().currentUser;
const userRef = doc(db, "users", user.uid);
const docSnap = await getDoc(userRef);
if (docSnap.exists()) {
const data = docSnap.data();
setUserDetails(data);
} else {
console.log("No such User!");
}
}
getUserDetails();
}, []);
return userDetails;
}
Whenever I do a console log from the HomeScreen it seems to first return null, then it returns the data. Is there something I'm doing wrong here (I'm sure it is) or is it standard behavior? Thank you in advance
I tried to run this multiple ways but those other functions that i have that also query the db seem to do the same thing. I don't know if it's something up with my async
This is expected behavior when UserInformation function is working as a custom hook.
The first time when HomeScreen component was initialized/mounted, the default value userDetails is null.
After a few seconds, the app fetches data from Firestore and updates userDetails state value which trigger a second rerender.
Note: Recommended best practice is always prefixed custom hooks function name use[FUNCTION_NAME] like useUserInformation.
Your logic is completely wrong. You couldn't wait on referencing hook function.
Even you can use useEffect hook if you want to get valid response.
function HomeScreen() {
const userDetails = UserInformation();
const clubDetails = ClubInformation();
const aircraftDetails = AircraftInformation();
useEffect(()=>{
if (userDetails) {
console.log(userDetails)
}
}, [userDetails])
if(!userDetails) {
return <Text>Loading...</Text>
}
if(!clubDetails) {
return <Text>Loading...</Text>
}
return <Text>Welcome {userDetails.first} {userDetails.last} {clubDetails.name}! This is a placeholder for future updates in the home screen</Text>
}
As I said in my comment you don't need to create your custom hook functions. It's enough with normal functions it will work like this.
async function getUserDetails() {
const user = getAuth().currentUser;
const userRef = doc(db, "users", user.uid);
const docSnap = await getDoc(userRef);
if (docSnap.exists()) {
const data = docSnap.data();
return data;
} else {
console.log("No such User!");
return null
}
}
function HomeScreen() {
const [userDetails, setUserDetails] = useState(null)
useEffect(()=>{
getUserDetails().then(data=>{
if (data != null) {
setUserDetails(data)
}
})
}, [])
if (!userDetails) {
return <Text>Loading...</Text>
}
return <Text>Welcome {userDetails.first} {userDetails.last}</Text>
}

How do I navigate to a certain screen given the presence of a document on firestore

This process takes place once the user is signed in. Once they are signed in, I want to check if they have a firestore document associated with their uid. If they do have one, send them to the homescreen. If they do not have one , send them to a "complete your profile page". Here is the code I have implemented so far:
/**Library Imports */
import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, View } from 'react-native'
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { StackActions } from '#react-navigation/native';
import firestore from '#react-native-firebase/firestore';
import AsyncStorage from '#react-native-async-storage/async-storage'
import auth from '#react-native-firebase/auth';
/**Screen Imports */
import HomeScreen from '../Screens/HomeScreen';
import FinishProfileScreen from '../Screens/login/FinishProfileScreen'
const Stack = createNativeStackNavigator();
const AppStack = () => {
let curUser = auth().currentUser;
let routeName;
const userRef = firestore().collection('users');
async function docExists(docName, docId) {
const docRef = firestore().collection(docName).doc(docId);
let docSnapshot = await docRef.get();
if (docSnapshot.exists) {
console.log("docExists True")
routeName = "HomeScreen"
return true;
} else {
console.log("docExists False")
routeName = "FinishProfileScreen"
return false;
}
}
docExists("users", curUser.uid)
console.log(routeName)
return (
<Stack.Navigator initialRouteName={routeName}>
<Stack.Screen
name = "Home"
component = {HomeScreen}
/>
<Stack.Screen
name = "FinishProfileScreen"
component = {FinishProfileScreen}
/>
</Stack.Navigator>
)
}
export default AppStack
This keeps navigating me to the homepage when I create a new user. It should notice that there is no firestore documents created and navigate to the FinishProfilePage. Furthermore, my debug console is confirming that the document does not exist, so why am I running into this issue? Thanks in advance!
LOG undefined
LOG docExists False
LOG undefined
LOG docExists False
LOG undefined
LOG docExists False
LOG undefined
LOG docExists False
LOG undefined
LOG docExists False
Seems you are calling docExists(docName, docId) and users collections at the same time so the user is undefined before using uid .Check if a user logged-in Firestore document exists using the useEffect hook. The checkDoc function will only be called when curUser changes by passing it in the dependency array of the useEffect hook. This ensures that the check only takes place when a user is logged in. If curUser is changed in any way, the useEffect will also re-render the component.
An example using the useEffect hook looks like the following:
useEffect(() => {
async function checkDoc() {
if(!curUser) return;
const docRef = firestore().collection("users").doc(curUser.uid);
let docSnapshot = await docRef.get();
if (docSnapshot.exists) {
console.log("docExists True");
routeName = "HomeScreen"
} else {
console.log("docExists False");
routeName = "FinishProfileScreen"
}
}
checkDoc();
}, [curUser]);

React Function to Component and Setting State with Function Return

here's the jist of where I'm stuck (or just read the title for my question).
I have a firebase.js file where I have functions to authenticate. signinGithub, signinGoogle, signinEmail and so forth. The Firebase Auth business logic is in these functions.
I am showing errors with console.log or alert from these functions. The functions are imported into a Component and I don't know how to capture the functions result into the component by somehow setting state from this out-of-component function file.
Here's a basic example:
firebase.js
...
const signInWithGitHub = async () => {
try {
const res = await signInWithPopup(auth, githubProvider)
const user = res.user
} catch (err) {
alert(err) // ** I want to pass "err" from here to Login
// ** component by updating Logins state for a message
}
}
export {signinWithGitHub}
...
Login.jsx
import React, { useEffect, useState } from "react"
import { useAuthState } from "react-firebase-hooks/auth"
import {
auth,
signInWithGitHub
} from "../lib/firebase"
function Login() {
const [user, loading, error] = useAuthState(auth)
render(
{* Below is the method call from the imported custom firebase function *}
<button onClick={signInWithGitHub}>
Login with GitHub
</button>
)
}
...
I was thinking something like this but I can't fully resolve it in my mind:
Set state in Login.js const [message, setMessage] = useState('')
When the imported signinWithGitHub has an error message --
I'm stuck figuring out how to apply to function message to the state, any ideas?
You can create a custom function inside your Login. jsx file to call the original signInWithGitHub method with a try catch block. And more importantly, you should not use render inside a functional component. Use return to render the JSX in DOM.
firebase.js
export const signInWithGitHub = async () => {
try {
const res = await signInWithPopup(auth, githubProvider);
const user = res.user;
} catch (err) {
throw new Error(err?.message || "Unable to sign in with GitHub");
}
};
Login.jsx
import React, { useEffect, useState } from "react";
import { useAuthState } from "react-firebase-hooks/auth";
import { auth, signInWithGitHub } from "../lib/firebase";
function Login() {
const [user, loading, error] = useAuthState(auth);
const [errorMessage, setErrorMessage] = useState("");
const onLogin = async () => {
try {
await signInWithGitHub();
} catch (err) {
setErrorMessage(err);
}
};
return (
<>
<button onClick={onLogin}>Login with GitHub</button>
{!!errorMessage && <h5>{errorMessage}</h5>}
</>
);
}

Have an error with Realtime Database from Firebase

// db.js file
import * as firebase from "firebase/app"
import "firebase/database"
const config = {
apiKey: "" ...
}
const db = firebase.initializeApp(config)
export default db
// App.vue file
import { reactive, onMounted, ref } from 'vue'
import db from "./db.js";
const SendMessage = () => {
const messagesRef = db.database().ref("messages")
if(inputMessage.value === "" || inputMessage.value === null) {
return
}
const message = {
username: state.username,
content: inputMessage.value
}
messagesRef.push(message)
inputMessage.value = ""
}
I try to make a little chat app with Vue.js and Firebase.
So i don't understand because i receive this when i try to send a message :
db_js__WEBPACK_IMPORTED_MODULE_1_.default.database is not a function
at Proxy.SendMessage (App.vue?3dfd:63:1)
I think it's about the import but i try to change for the V9 of firebase but that's didn't work.
Firebase V9 is build in functional aproach. Im working with firestore usually give me a sign if some thing not working.
db.js
import { initializeApp } from 'firebase/app';
import { getDatabase, ref, push, child, serverTimestamp } from 'firebase/database'
const config = {
apiKey: "" ...
}
const firebase = initializeApp(config)
const db = getDatabase()
function addMessage(path, message) {
message.createAt = serverTimestamp() // On database side database will assign current
// timestamp to this field so you will be able to order data
// from newest to oldest for example.
return push(child(ref(db, path)), message)
}
export { addMessage }
App.vue file
import { reactive, onMounted, ref } from 'vue'
import { addMessage } from "./db.js";
const SendMessage = async () => {
if (!inputMessage.value) return
// line above will check are value is "" or null by throwing
// false and using ! in front you changing it to true.
const message = {
username: state.username,
content: inputMessage.value
}
const result = await addMessage('path to data in tree', message)
// async/await will await until data is saved in database and then will do code bellow.
console.log(result.key) // If you await you can read result if result is not void.
inputMessage.value = ""
}
If you use ref() in .vue files make database operations outside of vue files database have same ref() function but they work different. You can allso change name of one function in import line import { ref as dbRef } from 'firebase/database'

Connection to Facebook with React and Firebase

i'm french, sorry for my little english.
I've a problem with Reactjs and Firebase, an error when i want connect with Facebook. I look tutorial in Udemy platform. This is a video for learn React
REBASE: The Firebase endpoint you are trying to listen to must be a string. Instead, got undefined
Parts of code Admin.js :
import React, { Component } from 'react'
import AjouterRecette from './AjouterRecette'
import AdminForm from './AdminForm'
import Login from './Login'
import firebase from 'firebase/app'
import 'firebase/auth'
import base, { firebaseApp } from '../base'
class Admin extends Component {
state = {
uid: null,
chef: null
}
componentDidMount () {
firebase.auth().onAuthStateChanged(user => {
if (user) {
this.handleAuth({ user })
}
})
}
handleAuth = async authData => {
console.log(authData)
const box = await base.fetch(this.props.pseudo, { context: this })
if (!box.chef) {
await base.post(`${this.props.pseudo}/chef`, {
data: authData.user.uid
})
}
this.setState({
uid: authData.user.uid,
chef: box.chef || authData.user.uid
})
}
authenticate = () => {
const authProvider = new firebase.auth.FacebookAuthProvider()
firebaseApp
.auth()
.signInWithPopup(authProvider)
.then(this.handleAuth)
}
...
export default Admin
Thank's
Have a good day.
......................................................................................................................................................................................................................................................................................................................................................................................................
I've got exactly the same problem, probably because I follow the same training as you.
Your error is here :
const box = await base.fetch(this.props.pseudo, { context: this })
because this.props.pseudo is null.
in app.js, in the admin component, write
pseudo={this.props.match.params.pseudo}
and not
pseudo={this.state.pseudo}
and that shoudl work.
regards

Categories