A way to fetch Microsoft Graph locations with PnPJs - reactjs

As stated above in the title I am currently facing issues fetching graph places with PnPJs, using the #pnp/graph graphfi factory interface in SPFx.
I am currently able to fetch data from my events via graphfi as can be seen below:
React.useEffect(() => {
graph = graphfi().using(SPFx(props.context));
getSpecificCalendar();
}, []);
const getSpecificCalendar = async () => {
await graph.me.events().then((e) => setCalendarEvent(e));
}
I have tried to get the places property from the graph object but to no avail. The only properties present are me and users but no option for places.
Esentially what I want to do is to graph.places. The conclusion I have come to is that #pnp/graph does not have any methods to get room data. Any ideas other than what I have tried above would be extremely helpful.

It looks like pnpjs does not have the /places endpoint implemented (yet). You could try using the built-in SPFx graph client for now. Something like:
const client = await props.context.msGraphClientFactory.getClient('3')
const response = await client.api('/places/......').get();
Alternatively, you could implement the /places endpoint yourself and submit a pull request for pnpjs :)

Related

Can you use aws-sdk/util-dynamodb unmarshall in Reactjs?

I have an API Gateway resource which calls a Dynamodb post request to query a table. I'm trying to call the API within my React app using Axios. The API is working, returning the data as expected (console log) but I'm getting errors if I try to use #aws-sdk/util-dynamodb (unmarshall) to convert the api data.items response into JSON and use within React.
./node_modules/#aws-sdk/util-dynamodb/dist-es/convertToNative.js 45:14 Module parse failed: Unexpected token (45:14)
Is there a way to use 'unmarshall' within React? Something like this:
useEffect(() => {
const getGoal = async () => {
try {
const response = await api.get(apiUrl)
setGoal(unmarshall(response.data.Items))
This works if I use a Lambda service, but I'm try to see if I can reduce my code.
While I'm not sure on the issue you are getting with unmarshall function, I would suggest using the DynamoDB Document Client which will return your data already unmarshalled.
The DynamoDB Document client simplifies working with items by abstracting the notion of attribute values. This abstraction annotates native JavaScript types supplied as input parameters, and converts annotated response data to native JavaScript types.

How to store data in this very simple React Native app?

I'm developing an app using React Native that allows you to create your own checklists and add items to them.
For example you'd have "Create Checklist", and inside that you'll have the option to "Add Item", "Delete Item" "Edit Item", basic CRUD methods etc.
It's going to be completely offline but I'm wondering what the best approach to storing this data locally would be.
Should I be using a DB such as firebase? I have read that it is overkill and to use something like Redux but I'm not sure if the latter will accomplish everything I need. As long as it's storing data which can be edited, and will save on the user's device (with minimal effort) it sounds good to me.
Would appreciate some input on this, thanks!
You could use AsyncStorage for persisting data locally on the user's phone. It is a simple persistent key-value-storage.
Each checklist is most likely an array of JS objects. The documentation provides an example on how to store objects.
const storeData = async (value) => {
try {
const jsonValue = JSON.stringify(value)
await AsyncStorage.setItem('#storage_Key', jsonValue)
} catch (e) {
// saving error
}
}
The value parameter is any JS object. We use JSON.stringify to create a JSON string. We use AsyncStorage.setItem in order to persist the data. The string #storage_Key is the key for the object. This could be any string.
We retrieve a persisted object as follows.
const getData = async () => {
try {
const jsonValue = await AsyncStorage.getItem('#storage_Key')
return jsonValue != null ? JSON.parse(jsonValue) : null;
} catch(e) {
// error reading value
}
}
Both examples are taken from the official documentation.
Keep in mind that this functionality should be used for persistence only. If the application is running, you should load the complete list, or parts of the list if it is very large, in some sort of application cache. The implementation for this functionality now heavily depends on how your current code looks like. If you have a plain view, then you could access the local storage in an effect and just store it in a local state.
function MySuperList() {
const [list, setList] = useState([]);
React.useEffect(() => {
// retrieve data using the above functionality and set the state
}, [])
// render list
return (...)
}
I would implement some sort of save button for this list. If it is pressed, then we persist the data in the local storage of the phone.

React js backend how to get the price_data info from stripe.checkout.session.line_items and push the data into firestore

I am trying to push the stripe checkout line_items price data to firestore by creating a webhook functions using react node js as the below code shown.
exports.stripeWebhook=functions.https.onRequest(async (req, res)=>{
const stripe = require("stripe")(functions.config().stripe.token);
let event;
try {
const whSec=functions.config().stripe.payments_webhook_secret;
event =stripe.webhooks.constructEvent(
req.rawBody,
req.headers["stripe-signature"],
whSec,
);
} catch (err) {
console.error("Webhook signature verification failed.");
return res.sendStatus(400);
}
const dataObject=event.data.object;
const session = await stripe.checkout.sessions.retrieve(dataObject.id, {
expand: ['line_items']
});
await admin.firestore().collection("customer").doc(String(dataObject.customer_email)).collection("order").doc().set({
checkoutSessionId:dataObject.id,
paymentStatus: dataObject.payment_status,
shppingInfo:dataObject.shipping,
amountTotal:dataObject.amount_total/100,
customerId:dataObject.customer,
CustomerEmail:dataObject.customer_email,
orderItems:session.line_items.price_data,
});
return res.sendStatus(200);
});
The function works fine except orderItems:session.line_items.price_data, it shows an error as an undefined firestore value. if I change to orderItems:session.line_items, it has no error, but the line_items info shown in firestore (screen shot below is not what I want, I just want the line_items.price_data which include just item title, price and images.
My question is how to get each item price_data from line_items?
You could try using the listLineItems method instead, and expand the product object inside data.price.product (according to the guide for expanding nested objects in lists).
const lineItems = await stripe.checkout.sessions.listLineItems(id, {expand: ['data.price.product']})
As you are currently retrieving the Session object with the expanded line_items data, this data won't include the product's name, images, description, etc. It looks like the problem is caused by these API calls, as opposed to something in your Firebase function or Firestore.
We can see that the product data from list_items.data.price.product is shown as expandable, which confirms it needs to be expanded. It also seems that there is no price_data field (but instead only price) nor product_data (but instead product) within the responses. These specific fields are apparently available only when creating Sessions.
You would end up with something like:
await admin.firestore().collection("customer").doc(String(dataObject.customer_email)).collection("order").doc().set({
//...
orderItems: lineItems.data[0].price //includes product details from nested expand
});
Since line items data is an array containing each item, you would need to build the array to save in Firestore as your use case requires. Let me know if this was helpful.

What is the best way to structure REST backend API calls with React?

Currently me and some colleagues are building a full stack web application, using React as our frontend framework. In this application, we need to perform CRUD operations on multiple resources, therefore multiple pages.
In my previous experience, I found tutorials/courses that put API calls in a services folder. Here's a simple example.
However, I realized this approach doesn't address loading/error states. So, I tried to come up with a solution using hooks, following another example I found: code.
This worked well for a feature I implemented, but I don't know how extensible it can be.
My question is, what is the better approach? Is there another one I didn't mention?
Reactjs is a library not a framework like Angular, there no one single approach how to handle your project structure. There are many alternatives, try to follow the good practices; if you are developing a big project that needs to scale use Redux as state management library, for me for a simple React project, we make folder called services and in an index file we prepare all our services :
/* root services ⚓️ .. */
import axios from 'axios';
const API_URL = 'http://yourapi.com/api/';
const headers = { 'Content-Type': 'application/json' };
const add = (data) => axios.post(`${API_URL}/form`, data, { headers });
const getData = () => axios.get(`${API_URL}/hotels`, { headers });
etc ...
export {
add,
getData
};
And for the call into Components
import { serviceName } from '../services/index';
serviceName({/*params if it's necessary */ })
.then(data => {
//---Get your Data
})
.catch(err => {
//---Handle your Api call error
});

How can I export static HTML pages from next.js when they need data from a third-party API?

I’m using next.js to build static HTML webpages.
One of my webpages needs data from a third-party API, which I’d like to fetch at build time and bake into the resulting HTML.
I don’t want this call to ever happen on the client, because:
CORS prevents the request from succeeding anyway
I would have to expose an API key on the client (no thank you)
I thought getInitialProps was the answer, because the fetched data is indeed baked in during the build/export process, but when I navigate away from the page and return from it, getInitialProps gets triggered on the client, breaking everything.
My current code in getInitialProps is something like:
static async getInitialProps(){
// Get Behance posts
const behanceEndpoint = `https://www.behance.net/v2/users/${process.env.BEHANCE_USERNAME}/projects?api_key=${process.env.BEHANCE_API_KEY}`
const behanceRes = await fetch(behanceEndpoint)
let behancePosts = await behanceRes.json()
// Return only the required number of posts
return {
behancePosts: behancePosts
}
}
Any advice or best practice on how to handle this? I know Gatsby.js does it out of the box.
one possibility would be, if you just want to execute this once on the server to check if the req parameter is present in getInitialProps: (Documentation)
req - HTTP request object (server only).
One dirty approach:
static async getInitialProps({ req }){
if (req) {
// only executed on server
// Get Behance posts
const behanceEndpoint = `https://www.behance.net/v2/users/${process.env.BEHANCE_USERNAME}/projects?api_key=${process.env.BEHANCE_API_KEY}`
const behanceRes = await fetch(behanceEndpoint)
let behancePosts = await behanceRes.json()
// Return only the required number of posts
return {
behancePosts: behancePosts
}
} else {
// client context
}
Hope this helps a little bit.

Resources