I was following along this tutorial to connect Firebase using react hooks. I followed everything but I am having a problem interacting with the real-time database on my project. For example, when I tried to insert data into the database, it doesn't make any changes it just shows null; I tried to see if it was other problems, tried it with different accounts, creating new projects, but nothing seems to work.
My App.js looks like this:
import React from "react"
import "./App.css"
import firebase from "./firebase"
function App() {
firebase
.firestore()
.collection("notes")
.add({
title: "Working",
body: "This is to check the Integration is working",
});
return (
<div className="App">
<h2>Note Taking App</h2>
<p>using React Hooks and Firebase</p>
<h3>Notes : </h3>
</div>
)
}
export default App
I checked the rules for the realtime database on firebase, and it shows:
{
"rules": {
".read": "now < 1610427600000", // 2021-1-12
".write": "now < 1610427600000", // 2021-1-12
}
}
My app runs properly, but on the console, since I was logging the XHRHttpRequests, it shows something is failing on the GET request.
It is a newly created project and I only changed the App.js and added firebase.js that looks exactly like the one in the guide.
The security rules you show are for the Firebase Realtime Database, but the code you have is accessing Cloud Firestore. While both databases are part of Firebase, they are completely separate and have different APIs.
To write to the Realtime Database would look something like this:
firebase
.database()
.ref("notes")
.push({
title: "Working",
body: "This is to check the Integration is working",
});
Related
Premise: I'm a newbie, so I'm aware that some of my questions or issues might sound obvious to the more experienced.
My situation is: I have an existing React frontend and Node backend. I need to add authentication to my app, so that I can provide login (and future registration) for my colleagues. We use AWS resources and there is an existing user pool in Cognito.
How do I go about doing this?
I've done some research and everything points me to AWS Amplify, but I've found the existing resources very confusing. Amplify seems to create a new, separate backend when I run amplify init, but I need to stick with the existing one.
Basically, all I need is the authentication piece, I don't want to use anything else from Amplify itself.
Apologies in advance if I might have missed something obvious. Thanks.
I have solved this exact situation with the Amplify library.
You can utilize the Authenticator component from #aws-amplify/ui-react where the docs are here.
In the most simple form, it would look like this:
import { Authenticator } from "#aws-amplify/ui-react";
import Amplify from "aws-amplify";
Amplify.configure(awsExports);
const App = () => {
return (
<Authenticator>
{/* Pass app entry as children */}
{({ signOut, user }) => <Home signOut={signOut} user={user} />}
</Authenticator>
);
};
//Object holding AWS auth config
//This is a seperate file which is imported
export const awsExports = {
Auth: {
mandatorySignIn: true,
region: "YOUR REGION",
userPoolId: "COGNITO_POOL_ID",
userPoolWebClientId: "COGNITO_CLIENT_ID",
},
};
So in my app, I only use this Authenticator component which does all of the interactions with the cognito pool and nothing else from Amplify. There's a number of different props you can pass into the Authenticator component so certainly review the docs.
I can login and logout users on Next.js after reading these resources amongst others:
The Ultimate Guide to Next.js Authentication with Auth0
#auth0/nextjs-auth0 library
API Call Example
SPA + API: Node.js Implementation for the API
But nowhere could I find out if I can delete users using the auth0/nextjs-auth0 library.
I also looked into the module's handlers here.
Am I right to think there is no way to delete a user using the #auth0/nextjs-auth0 library?
If yes, what is the most preferred way to delete a user? I'd like to allow users to click a button in the browser to delete themselves from Auth0.
At this point, I'm thinking of using node-auth0 library to do it following this solution:
management.users.delete({ id: USER_ID }, function (err) {
if (err) {
// Handle error.
}
// User deleted.
});
But it requires a node back end, which I sort of wanted to avoid. Even so, is this the best solution or are there better ones? The Auth0 ecosystem is quite sprawling.
Edit 27 Oct 2020: Will try using node-auth0 library in "serverless" function in Next.js to allow user to delete their account over the weekend. Secrets are hidden with Next's runtime configuration. If this is not the best way to do it, please let me know. Thanks.
I believe you mean logging out a user by "deleting a user". Because If you want to delete a user from the database, you have to have node server which handles the db connection. If you want to log out the user, in "pages/api/v1" create a logout.js. in next.js, serverless functions or api functions are written in "pages/api".
import auth0 from "/utils/auth0";
// auth0 file is where you set the configuration for the auth0.
export default async function logout(req,res) {
try {
await auth0.handleLogout(req, res);
} catch (error) {
console.error(error);
res.status(error.status || 400).end(error.message);
}
}
I'm building a React app that will use Firebase Auth. I was storing my API key inside the .env file but I've read in the React docs that it is not safe, so I have created a custom and private route on my NodeJS server that is a simple GET request which sends me the data that I need(key, projectid, etc). And I think this is the safest way to do it, right?
Now I'm trying to get this data from my backend and I'm able to do it using console.log for example but I'm unable to integrate it with Firebase function. It keeps saying that it is undefined.
This is what I have tried so far:
import * as firebase from 'firebase/app';
import 'firebase/auth';
const API_URL = process.env.REACT_APP_API_URL;
let res;
export async function getFirebaseKeys() {
const response = await fetch(`${API_URL}/api/get`);
res = response.json();
}
getFirebaseKeys();
//I have also tried to use firebase.OnLog but no success.
//I have also tried to wrap firebase.initializeApp and my fetch in a function but it breaks
const app = firebase.initializeApp({
apiKey: res.apiKey,
authDomain: res.domain,
databaseURL: res.database,
projectId: res.projectId,
storageBucket: res.storageBucket,
messagingSenderId: res.senderId,
});
export default app;
This is my first project with Firebase and React so I'm sorry if i have missed something obvious.
What you're trying to do now is not really any safer than putting the Firebase config in the source (where it's intended to go). Hiding it behind a GET just makes people go through another step to get a hold of it if they want it.
There's nothing unsafe about putting the Firebase config in the hands of the public, as long as you are also signing in users with Firebase Authentication, and using security rules to determine who can access what data in the project.
Just do whatever is most convenient - security is not the issue here.
See also: Is it safe to expose Firebase apiKey to the public?
I have an Angular 7 site, that works fine without server-side rendering (SSR). I host it using Google's Firebase hosting. I now want to setup SSR. I followed this guide and got it to build and deploy to Firebase Hosting and Functions.
However, the site does not load and the Functions logs include this entry:
ERROR ReferenceError: document is not defined
at new CssKeyframesDriver (/user_code/node_modules/#angular/animations/bundles/animations-browser.umd.js:4246:26)
at instantiateSupportedAnimationDriver (/user_code/node_modules/#angular/platform-browser/bundles/platform-browser-animations.umd.js:412:88)
at _callFactory (/user_code/node_modules/#angular/core/bundles/core.umd.js:19867:24)
at _createProviderInstance (/user_code/node_modules/#angular/core/bundles/core.umd.js:19825:30)
at resolveNgModuleDep (/user_code/node_modules/#angular/core/bundles/core.umd.js:19786:25)
at _createClass (/user_code/node_modules/#angular/core/bundles/core.umd.js:19854:72)
at _createProviderInstance (/user_code/node_modules/#angular/core/bundles/core.umd.js:19822:30)
at resolveNgModuleDep (/user_code/node_modules/#angular/core/bundles/core.umd.js:19786:25)
at _callFactory (/user_code/node_modules/#angular/core/bundles/core.umd.js:19873:71)
at _createProviderInstance (/user_code/node_modules/#angular/core/bundles/core.umd.js:19825:30)
Any ideas of what is wrong? I can provide code snippets or individual read access to the repo if requested.
Server side rendering probably means serving HTML from Node.js w Express.js. In the Firebase suite of products, this is accomplished using Cloud Functions for Firebase's HTTP triggers.
You can have a look at Firebase Samples on Github. This is a relatively advanced implementation so proceed as long as you are strong in JavaScript, HTML, and CSS (not to mention Angular).
Angular SSR is trying to run angular animations but it's not able to find any document variable(there is no document on server-side).
You can solve this by conditionally executing your code with the help of isPlatformBrowser and isPlatformServer.
example
Import this
import { Component, PLATFORM_ID } from '#angular/core';
import { isPlatformBrowser, isPlatformServer } from '#angular/common';
User like this
constructor(#Inject(PLATFORM_ID) platformId: string){
this.isBrowser = isPlatformBrowser(platformId);
this.isServer = isPlatformBrowser(platformId);
if(this.isBrowser){
//Do something on the browser
}
if(this.isServer){
//Do something on the server
}
}
I'm trying to get google calendar events into my React Redux app.
I've tried using googleapis and google-auth-library but webpack is throwing errors because googleapis was built to run server side and bundle.js is referenced from client.
So I've read a few forums about these errors and they all point to using Google's js client library instead.
I understand how to implement this in a java or php app (I'm old... 35 ;) but I'm new to React Redux and I'm looking for the best way to implement this.
I'm trying to fetch the events from my calendar in my actions.js. I tried including <script src="https://apis.google.com/js/api.js"></script> in my html header and then using gapi.load() from actions.js. I also tried creating a api.js file and referencing that with require('./api'). I also tried to use the cli commands from the Node.js Quickstart guide to get an access_token and then just use axios to call Google API directly but I'm getting a 403. I'm thinking I'm just not providing the proper headers but that wouldn't be best practice anyway.
My question is basically how do I reference Google's js client library from my actions.js file while adhering to Redux standards?
You're on the right track by including the official Google client API in the HTML header. It's less than ideal -- it would be nice if Google provided the (browser) client API as an npm module that you could import. But they don't (that I see), so I think what you're doing is fine.
Then there's the question of "how do I use it in a way that's React/Redux friendly?" Redux is a mechanism for managing the state of your application. The Google API is not part of your application (though what you do with it may inform the state of your application).
It's easy to verify that you have access to the Google API: you can just make a call from the componentDidMount method of one of your components, and do a console log:
class MyComp extends React.Component {
componentDidMount() {
// this is taken directly from Google documentation:
// https://developers.google.com/api-client-library/javascript/start/start-js
function start() {
// 2. Initialize the JavaScript client library.
gapi.client.init({
'apiKey': 'YOUR_API_KEY',
// clientId and scope are optional if auth is not required.
'clientId': 'YOUR_WEB_CLIENT_ID.apps.googleusercontent.com',
'scope': 'profile',
}).then(function() {
// 3. Initialize and make the API request.
return gapi.client.request({
'path': 'https://people.googleapis.com/v1/people/me',
})
}).then(function(response) {
console.log(response.result);
}, function(reason) {
console.log('Error: ' + reason.result.error.message);
});
};
// 1. Load the JavaScript client library.
gapi.load('client', start);
},
}
If you don't see what you expect on the console, somehow gapi isn't getting loaded as you expect. If that happens, you'll have a more specific question you can ask!
If you do get a response, you now know how to call GAPI...but then how to make use of it in a Redux-friendly way?
When you make a GAPI call, you probably want to modify your application's state in some way (otherwise why would you be doing it?) For example, you might invoke the auth flow, and when GAPI returns success, your application state now has loggedIn: true or similar (possibly with lots of other state changes). Where you make the GAPI call is up to you. If you want to do it when the component loads, you should do it in componentDidMount. You also may commonly be making the GAPI call in response to a user action, such as clicking on a button.
So the typical flow would be something like this:
// either in componentDidMount, or a control handler, usually:
someGapiCall()
.then(result => {
this.props.onGapiThing(result.whatever)
})
Where this.props.onGapiThing is a function that dispatches an appropriate action, which modifies your application state.
I hope this overview helps...feel free to follow up with more specific questions.
Can you try this library which I used to load external libraries and modules in my React app when I couldn't find a NPM module for it:
https://github.com/ded/script.js/
So your code will be like this:
import $script from 'scriptjs';
$script('https://apis.google.com/js/api.js', function () {
//Put your google api functions here as callback
});
I'm going to answer my own question despite some very good correct answers.
#MattYao answered my actual question of how to get a js script available for reference in my actions.js file.
#Ethan Brown gave a very detailed answer that showed some excellent flow possibilities.
#realseanp changed the scope but a valid answer.
I tried all of the above and they worked.
So I'm not sure what I was doing wrong but I was finally able to access the gapi object from actions.js by just adding <script src="https://apis.google.com/js/api.js"></script> to my index head.
I'm using pug so it looks like this:
doctype
html
head
title MyTitle
link(rel='stylesheet' href='/static/css/main.css')
link(rel='stylesheet' href='/static/css/react-big-calendar.css')
script(src='https://apis.google.com/js/api.js' type='text/javascript')
body
div(id='app')
script(src='/static/bundle.js' type='text/javascript')
Here is my component file:
import React from 'react'
import BigCalendar from 'react-big-calendar';
import moment from 'moment';
import { connect } from 'react-redux'
import { fetchEvents } from '../actions/actions'
BigCalendar.momentLocalizer(moment);
#connect((store) => {
return {
events: store.events.events
}
})
export default class Calendar extends React.Component
{
componentWillMount()
{
this.props.dispatch(fetchEvents())
}
render()
{
return (
<div>
<BigCalendar
events={this.props.events}
startAccessor='startDate'
endAccessor='endDate'
style={{height: 800}}
/>
</div>
)
}
}
And then I was able to get this working in my actions.js file
export function fetchEvents()
{
return (dispatch) =>
{
function start()
{
// 2. Initialize the JavaScript client library.
gapi.client.init({
'apiKey': API_KEY,
// clientId and scope are optional if auth is not required.
'clientId': CLIENT_ID,
'scope': 'profile',
}).then(function() {
// 3. Initialize and make the API request.
return gapi.client.request({
'path': 'https://www.googleapis.com/calendar/v3/calendars/MY_EMAIL#gmail.com/events?timeMax=2017-06-03T23:00:00Z&timeMin=2017-04-30T00:00:00Z',
})
}).then( (response) => {
let events = response.result.items
dispatch({
type: 'FETCH_EVENTS_FULFILLED',
payload: events
})
}, function(reason) {
console.log(reason);
});
};
// 1. Load the JavaScript client library.
gapi.load('client', start)
}}
I had to make my calendar public to access it this way. So now I'm going to work on the oauth2 stuff :/
I would load all the google stuff in my index file before i loaded my webpack bundle (Option 1) . Then I would use redux sagas to call the google apis. Loading the google code before your webpack bundle will ensure everything is ready to go when you call the api from the saga
Try this package.
It looks like it is updated.
https://github.com/QuodAI/tutorial-react-google-api-login