Property 'calendar' does not exist on type 'typeof client' - reactjs

I'm trying to connect my Google Calender to my React website. I've got a component called Calendar. I've used the JS tutorial from Google and I've changed it to work in Typescript. I've got the authentication and authorization already working, however fetching data from the calendar is not working. I'm getting the following error when compiling/editing.
[ts] Property 'calendar' does not exist on type 'typeof client'. Did you mean 'calendars'?
I've already downloaded the types for the gapi.client.calendar and as you can see in the image below, they are also found in the #types folder. I'm kind of stuck and I don't know how I can fix this issue..
Here is my code from my Calendar.tsx
import * as React from 'react';
import { Button } from 'semantic-ui-react'
import googleApiKey from '../googleapi-key.json';
const CLIENT_ID = googleApiKey.CLIENT_ID;
const API_KEY = googleApiKey.API_KEY;
const DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"];
const SCOPES = "https://www.googleapis.com/auth/calendar.readonly";
class Calendar extends React.Component {
constructor(props: any) {
super(props);
console.log(CLIENT_ID);
console.log(API_KEY);
this.handleClientLoad = this.handleClientLoad.bind(this);
this.handleAuthClick = this.handleAuthClick.bind(this);
this.handleSignoutClick = this.handleSignoutClick.bind(this);
this.initClient = this.initClient.bind(this);
this.updateSigninStatus = this.updateSigninStatus.bind(this);
this.listUpcomingEvents = this.listUpcomingEvents.bind(this);
}
componentDidMount() {
this.initClient();
}
public render() {
return (
<div>
<Button onClick={this.handleAuthClick}>
authorizeButton
</Button>
<Button onClick={this.handleSignoutClick}>
signoutButton
</Button>
</div>
);
}
/**
* On load, called to load the auth2 library and API client library.
*/
public handleClientLoad() {
gapi.load('client:auth2', this.initClient);
}
/**
* Sign in the user upon button click.
*/
public handleAuthClick(event: any) {
gapi.auth2.getAuthInstance().signIn();
}
/**
* Sign out the user upon button click.
*/
public handleSignoutClick(event: any) {
gapi.auth2.getAuthInstance().signOut();
}
/**
* Initializes the API client library and sets up sign-in state
* listeners.
*/
public async initClient() {
await gapi.client.init({
apiKey: API_KEY,
clientId: CLIENT_ID,
discoveryDocs: DISCOVERY_DOCS,
scope: SCOPES
})
// Listen for sign-in state changes.
gapi.auth2.getAuthInstance().isSignedIn.listen(this.updateSigninStatus);
// Handle the initial sign-in state.
this.updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
}
/**
* Called when the signed in status changes, to update the UI
* appropriately. After a sign-in, the API is called.
*/
public updateSigninStatus(isSignedIn: any) {
if (isSignedIn) {
this.listUpcomingEvents();
}
}
/**
* Print the summary and start datetime/date of the next ten events in
* the authorized user's calendar. If no events are found an
* appropriate message is printed.
*/
public listUpcomingEvents() {
console.log(gapi.client.calendar); // <--- Compile error: Does not recognize calendar
}
}
export default Calendar;
EDIT
When performing console.log(gapi.client) I can see that the client contains a calendar object (see image). But why can't I reach it in my own code?

I managed to fix my own problem. After performing console.log(gapi.client) I noticed that calender was already there, so I tried the following gapi.client['calendar'] and it worked as it should. I don't know why Typescript does not recognize the calendar in the first place, so if anybody has an idea feel free to leave a comment.

Try the following
Install types npm i #types/gapi.client.calendar
Include https://apis.google.com/js/api.js & https://apis.google.com/js/platform.js in index.html
Add the following inside types in tsconfig.app.json
"types": [
"gapi",
"gapi.auth2",
"gapi.client",
"gapi.client.calendar"
]

You have to add:
"types": ["gapi", "gapi.auth2", "gapi.client", "gapi.client.calendar"]
in tsconfig.app.js and in tsconfig.json.

Related

Adding into sharepoint list using react js spfx webpart

I am using this code in my webpart to insert into the sharepoint list with list name, but moving this code into production environment is creating an issue since its forming the wrong url for inserting into the list, The url in production is
https://abcportal.sharepoint.com/sites/SolutionBook/SitePages/_api/web/lists/getByTitle('Smart%20City%20IAQ%20Demo%20Requests')?$select=ListItemEntityTypeFullName
But in local environment is working fine it forms this url
https://abcportal.sharepoint.com/sites/solutionbooktest/_api/web/lists/getByTitle('Smart City IAQ Demo Requests')/items
In the production environment URL SitePages is coming automatically, how to remove it?
-------Code---------
public insertEmailToList() {
pnp.sp.web.lists.getByTitle("Smart City IAQ Demo Requests").items.add({
Title: this.state.Email
}).then(r => {
this.setState({ ButtonActive: false });
});
}
or Is there any way to insert into sharepoint list using URL of the list?
You need to establish the SPFx context for PnPJs. This can be done in the onInit() method of your web part through the setup() method imported from #pnp/core or #pnp/sp.
Using #pnp/core setup
import { setup as pnpSetup } from "#pnp/core";
// ...
protected onInit(): Promise<void> {
return super.onInit().then(_ => {
// other init code may be present
pnpSetup({
spfxContext: this.context
});
});
}
// ...
Using #pnp/sp setup
import { sp } from "#pnp/sp/presets/all";
// ...
protected onInit(): Promise<void> {
return super.onInit().then(_ => {
// other init code may be present
sp.setup({
spfxContext: this.context
});
});
}
// ...
Refer to this link for more details.

Building Credential object needed for Firebase Reauthentication

When trying to build the credential object to reauthenticate a user with Firebase and ReactJS, I am getting cannot read property 'credential' of undefined where undefined is referring to this.app.auth.EmailAuthProvider which should be firebase.auth.EmailAuthProvider.
I have read that it is a static method and cannot be called on an instance, but I am not sure what exactly that means or how to correct my implementation to get the credential needed. I am calling the method in a class based component, but I am still unaware of how all of this ties in to calling a static method.
The method that I am calling is 'this.app.auth.EmailAuthProvider.credential()'
reAuthUser = (data) => {
// console.log('email: ', data.userEmail, 'password: ', data.password);
const userCredential = this.app.auth.EmailAuthProvider.credential(
data.email,
data.password
)
// this.currentUser.reauthenticateWithCredential(data.userEmail, data.password)
// .then(function() {
// alert('user has been reauthenticated')
// }).catch(function(error) {
// console.log('reauth error: ', error)
// })
};
This is in ReactJS, in a class component. this.app is a reference to Firebase and it is called in the constructor:
constructor(props) {
super(props);
this.app = Firebase;
this.currentUser = this.app.auth().currentUser;
};
I know similar questions have been asked and answers have been approved, but they don't make much sense to me at this point.
Assuming that this.app.auth is an instance of the firebase.auth.Auth class, EmailAuthProvider won't be present on that object, as it is not part of the prototype for the firebase.auth.Auth class.
EmailAuthProvider is instead part of the firebase.auth namespace which means it can only be accessed using firebase.auth.EmailAuthProvider (note how auth is not called as a function).
If using imports, you could also use
import { auth as FirebaseAuth } from 'firebase';
FirebaseAuth.EmailAuthProvider.credential(...)

How can I access a library through a script in a Typescript React app?

I am fairly new to React, and have not done any extensive web development in years, so am struggling with a (probably) basic web issue:
I am implementing a Stripe based payment flow in a React web app (written in Typescript), and have hit a roadblock on step 2 (adding a redirect to checkout client-side).
The quickstart guide instructs me to insert the following script tag on my website, which I have done through inserting the tag inside the <head> tag:
Checkout relies on Stripe.js. To get started, include the following
script tag on your website—it should always be loaded directly from
https://js.stripe.com:
<script src="https://js.stripe.com/v3/"></script>
The next step is where I am having a problem (using the ESNext syntax since this is in a Typescript project):
Next, create an instance of the Stripe object by providing your publishable API key as the first parameter:
const stripe = Stripe('pk_test_sdjxyNjHWmRefdkUNYuS53MA00Ot1f9HOu');
I would like to access Stripe through a service worker, rather than a component directly. However, trying to initialise the stripe instance is not working. I have tried:
importing the Stripe module in various ways, which hasn't worked
adding a dependency on #types/stripe, which seems to prevent the compiler complaining
Currently, my StripeService.ts file has the following code:
const stripe = Stripe("SOME_KEY");
export const redirectToCheckout = (sessionId: string) => {
return stripe.redirectToCheckout(
{
sessionId: sessionId,
});
};
Localhost instance is giving this error:
/src/services/stripe/StripeService.ts
Line 12: 'Stripe' is not defined no-undef
Any suggestions on how I can resolve this issue? I have looked into the react-stripe-elements wrapper, but that is geared towards providing UI components, whereas I only want the Stripe checkout API call behaviour.
Bare Minimum
Minimum implementation is to declare Stripe using any:
declare class Stripe {
constructor(...args: any[]);
redirectToCheckout(...args: any[]): any;
}
const stripe = new Stripe("pk_test_sdjxyNjHWmRefdkUNYuS53MA00Ot1f9HOu");
stripe.redirectToCheckout({
sessionId: sessionId
})
Stronger Typings
You can of course expand this by more explicitly typing the parts that you need:
declare class Stripe {
constructor(publicKey: string);
redirectToCheckout({
sessionId
}: {
sessionId: string;
}): Promise<{ error: Error }>;
}
const stripe = new Stripe("pk_test_sdjxyNjHWmRefdkUNYuS53MA00Ot1f9HOu");
stripe.redirectToCheckout({
sessionId
}).then(function (result) {
// If `redirectToCheckout` fails due to a browser or network
// error, display the localized error message to your customer
// using `result.error.message`.
});
Try using the windows object instead:
var stripe = window.Stripe("pk_test_h4naRpZD1t2edp2HQKG2NrZi00rzz5TQJk");
For a service file, you would just add stripe to package.json, then in the file would do:
import Stripe from "stripe";
const stripe = Stripe("SOME_KEY");
export const redirectToCheckout = (sessionId: string) => {
return stripe.redirectToCheckout(
{
sessionId: sessionId,
});
};
You would use the public key in the client side, and the secret key in the server side. You should keep stripe object (Stripe('pk_test_sdjxyNjHWmRefdkUNYuS53MA00Ot1f9HOu')) in your state somehow to be able to retrieve it later.
An example call could be like this:
client side
const {paymentMethod, error} = await this.state.stripe.createPaymentMethod('card', cardElement, {
billing_details: {
name: 'Jenny Rosen',
},
});
StripeService.makePayment(paymentMethod);
server side
import Stripe as "stripe";
const stripe = Stripe("SOME_KEY");
export const makePayment = (paymentMethod: object) => {
...
};

React Google API

I am new to React and RN. I have looked into every single solution here but I did not find a solution for my case. I am trying to pull google calendar events from calendar v3 api. I have tried two ways, so far. I don't know which one is correct but I did not get a correct result for any of them. Firstly, I have tried to send a request to the https://www.googleapis.com/calendar/v3/calendars/${CALENDAR_ID}/events?key=${API_KEY}( I don't know if the key parameter is needed. I think we should delete key parameter in front of the api key.I did it like that because otherwise it was giving an error as global not found).
This is calendar.js
const CALENDAR_ID = 'public#qeqw'
const API_KEY = 'key'
let url = `https://www.googleapis.com/calendar/v3/calendars/${CALENDAR_ID}/events?key=${API_KEY}`
export function getEvents (callback) {
request
.get(url)
.end((err, resp) => {
if (!err) {
const events = []
JSON.parse(resp.text).items.map((event) => {
events.push({
start: event.start.date || event.start.dateTime,
end: event.end.date || event.end.dateTime,
title: event.summary,
})
})
callback(events)
}
})
}
This is app.js
import React from 'react'
import { render } from 'react-dom'
import { getEvents } from './gcal'
import { View, Text,
StatusBar,Image,AppRegistry,ScrollView,StyleSheet,Platform,FlatList} from
'react-native'
class App extends React.Component {
constructor () {
super()
this.state = {
events: []
}
}
componentDidMount () {
getEvents((events) => {
this.setState({events})
})
}
render () {
return (
// React Components in JSX look like HTML tags
<View>
<Text>{this.state.events}</Text>
</View>
)
}
}
However, I got an error in the below. I don't know what I am doing wrong but it should be possible to send a request like that. My only concern is that if I need to get token by giving my client information by using OAuth2 authentication. Do I need to sign up and and get token to reach the API? If I need to do it, I have implemented to do it in node js by reading the sample here.https://developers.google.com/calendar/quickstart/nodejs but there are some node modules which I cannot use them in my React native application like fs, googleAuth, readline etc... Some of them can be done by using nodeify but others throw an error. So, I don't know what to do from now on. If someone can guide me how I would use google calendar api in react, I'd be appreciated. Thanks to the everyone who contributes here.
{
"error": {
"errors": [
{
"domain": "usageLimits",
"reason": "dailyLimitExceededUnreg",
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.",
"extendedHelp": "https://code.google.com/apis/console"
}
],
"code": 403,
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."
}
}
As the error message indicates, you are beyond your usage for that API.
You need to sign up in order to continue to use the API.
Once you sign up, you can use a library like Request-Promise in order to make the API request.
OR
You can search npm for a react component that interfaces with the Google Calendar API, such as this one
The error is caused from an silly mistake. The key parameter in the url should not be in parenthesizes. The reason it did not work is that the parameter key which is in front of the api key is in parenthesize. If you delete it, it works like a charm.

Reading data from Firebase 3 into a React component with ES6 syntax

I've been struggling with a simple use case: read a number, ie signed-up user counts, on my React web app from Firebase Database and display it when the page is loaded.
There is documentation for older versions of React and Firebase, but it would seem that this use case should be doable the new way.
Screenshot of my Firebase Database.
import React from 'react'
import {Badge} from 'react-bootstrap'
var firebase = require('firebase')
var config = {
apiKey: "MyKey", // redacted key
authDomain: "dnavid-c48b6.firebaseapp.com",
databaseURL: "https://dnavid-c48b6.firebaseio.com",
storageBucket: "dnavid-c48b6.appspot.com",
};
var firebaseApp = firebase.initializeApp(config);
var UCRef = firebaseApp.database().ref("numberofusers")
class UserCount extends React.Component{
constructor(props){
super(props)
this.state = {usercount: '3'}
}
componentDidMount() {
// this.setState({usercount:4}) // This actually works and displays "4"
var uc = UCRef.on('value',function(snapshot){return(snapshot.val())})
debugger;
this.setState({usercount:uc}) // This does not work
}
render(){
return (
<Badge>
{this.state.usercount}
</Badge>
)
}
}
export default UserCount;
In the Chrome debugger (note "debugger" command) I get in the console:
> uc
<. function(snapshot) {
return snapshot.val();
}
And
> uc()
Uncaught TypeError: Cannot read property 'val' of undefined(…)
From which I would deduce that since the snapshot is undefined, the event has not been triggered. But this doesn't sound logical as:
componentDidMount has been evaluated (because the component has rendered and the execution reaches it when the debugger stops for inspection)
Firebase documentation claims that the event is triggered, see below "This method is triggered once when the listener is attached".
Value events
You can use the value event to read a static snapshot of the contents
at a given path, as they existed at the time of the event. This method
is triggered once when the listener is attached and again every time
the data, including children, changes. The event callback is passed a
snapshot containing all data at that location, including child data.
If there is no data, the snapshot returned is null.
So, is the listener not being attached? What's going on?
You need to do it like this:
componentDidMount() {
UCRef.on('value', snapshot => {
this.setState({usercount: snapshot.val()});
});
}
UCRef.on('value', func) would not return you a value. You can get it inside a callback

Resources