How do I use next auth getServerSession in next js 13 beta server component in app directory - session

I'm using next auth v4 with next js 13 beta with server component, everything working fine. But I have a situation where I will need to know the logged user id, since I'm using next auth, I have access to session, I can use useSession() but then I will need to make the component a client component, So I want to use it on server, I can use getServerSession in api since I have access to req & res object, but in next js beta with new app dir, I can't do it. Please let me know if you know how to fix the issue. Thank you
import { getServerSession } from "next-auth";
import { authOptions } from "#/pages/api/auth/[...nextauth]";
const Test = async () => {
const user_id = 1; // How do I get user id from session, user_id is available in session
// I don't have access req & res object in server component.
const data = await getServerSession(request, response, authOptions);
console.log(data);
});
return (
<></>
);
};
export default Test;
Didn't find enough information

I found an answer, in next js 13 beta, you wont need to use request & response object, just use the authOptions, it will work
import { getServerSession } from "next-auth";
import { authOptions } from "#/pages/api/auth/[...nextauth]";
const Test = async () => {
const data = await getServerSession(authOptions);
console.log(data);
});
return (
<></>
);
};
export default Test;

Related

fetch weatherapi.com with async await react hooks

Can anyone help me why my code doesn't work to fetch API?
I have to build a weather app from several components, must build it structured.
My plan is to have one service component that I have API service in there. then I have to make 3 more components, search component to handle the city search, weatherToday component to show today weather, and weatherForecast component to show five days forecast.
And I have to fetch the API with async an await. Here is the code that I tried(just now I have the code in my App.js just to try if my fetch work)
import { useState, useEffect } from "react";
function App() {
const [data, setData] = useState();
const fetchData = async () => {
await fetch(
`http://api.weatherapi.com/v1/forecast.json?key=1d172d3904e246849d3183628230802&q=Stockholm&days=6&aqi=no&alerts=no`
)
.then((response) => {
return response.json();
})
.then((data) => {
setData(data);
});
};
useEffect(() => {
fetchData();
}, []);
return (
<>
<h3>{data.location.name}</h3>
<p>{data.current.temp_c}</p>
<p>{data.location.localtime}</p>
</>
);
}
export default App;
First of all, welcome to React and StackOverflow!
There's a few issues here:
The main issue is CORS. You can't call this API from your browser - it's meant to be called from a server (backend). I highly recommend using Next.js since you like React, it uses that as it's framework - but it allows you to have Server Components, essentially an Express backend, so that you can perform this API call - then retrieve that data using this client component just to display the data (not to fetch it).
Another issue (but not the problem here) is reusing the data variable in the local scope of then((data) => is not good when you have data defined higher up in the component scope for your state. Use then((d) => instead.
I created a Next.js 13 sandbox for you with this working API call to get you started:
https://codesandbox.io/p/sandbox/broken-field-4nsp1p
In Next.js 13, you can use the app folder, where every component is a Server Component by default. Then you can create Client Component, like the one you have above - you simply have to add use client to the very top of the file, that's it.
Since Next.js 13 is very new (the app folder and concept of Server Components very new and bound to change), you would want to potentially just stick with the pages folder.
In there, you'll see the client component which calls the api folder's getWeather API call.
Finally, you shared your private key with the public. You need to destroy and regenerate that key now:
From the WeatherAPI.com Docs:
Authentication
API access to the data is protected by an API key. If at anytime, you
find the API key has become vulnerable, please regenerate the key
using Regenerate button next to the API key.
https://www.weatherapi.com/docs/
If don't want to use Next.js - then you'll need to use some sort of backend, like Firebase Functions or Google Cloud Functions, etc. Next.js is probably the easiest thing to adapt if you like React though!
Learn about Next.js 13 & /app folder:
https://beta.nextjs.org/docs/getting-started
Learn about Next.js 12 & /pages folder:
https://nextjs.org/docs
Implementing Fetch via Next.js 13
app/head.tsx
export default function Head() {
return (
<>
<title>Weather App</title>
<meta content="width=device-width, initial-scale=1" name="viewport" />
</>
);
}
app.layout.tsx
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
{/*
<head /> will contain the components returned by the nearest parent
head.tsx. Find out more at https://beta.nextjs.org/docs/api-reference/file-conventions/head
*/}
<head />
<body>{children}</body>
</html>
);
}
app/page.tsx
const App = async () => {
console.log("App.js");
const results = await fetch(
`http://api.weatherapi.com/v1/forecast.json?key=1d172d3904e246849d3183628230802&q=Stockholm&days=6&aqi=no&alerts=no`
);
const json = await results.json();
console.log("json", json);
return (
<>
<h3>{json.location.name}</h3>
<p>{json.location.temp_c}</p>
<p>{json.location.localtime}</p>
</>
);
};
export default App;
When visiting either / or /weather, you will see the same results, since the example is implemented in both v12 and v13:
--- OR --- Implementing Fetch via Next.js 12
pages/weather.tsx
async function getData() {
const res = await fetch("/api/getWeather");
console.log("res", res);
// The return value is *not* serialized
// You can return Date, Map, Set, etc.
// Recommendation: handle errors
if (!res.ok) {
// This will activate the closest `error.js` Error Boundary
throw new Error("Failed to fetch data");
}
const json = await res.json();
console.log({ json });
return json;
}
export default async function Page() {
const data = await getData();
console.log("data", data);
return (
<main>
<h3>{data.location.name}</h3>
<p>{data.current.temp_c}</p>
<p>{data.location.localtime}</p>
</main>
);
}
pages/api/getWeather.ts
import { NextApiRequest, NextApiResponse } from "next";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const results = await fetch(
`http://api.weatherapi.com/v1/forecast.json?key=1d172d3904e246849d3183628230802&q=Stockholm&days=6&aqi=no&alerts=no`
);
const json = await results.json();
console.log("json", json);
res.status(200).send(json);
}
Remember to revoke your exposed secret API key.
I hope this helps you start building your app. Good luck!

Shopify App Rejected Due To Redirecting To A Different Page When Attempting To Install Your App in incognito

I have created a Shopify public app using node with Shopify CLI, So after i have submitted the app for the reviewing in the Shopify app store.
So the review team rejected the app mentioning the app is not directed to the oAuth page when we install the app ( in Incognito ) window in normal browser their is not mush issue.
The redirecting page in incognito
The issue that point out buy the ShopifyThe replay mail from the review team
The issue only occur in the incognito tab, ie when we log in to our partner dashboard from the Incognito and select the app and choose the "test on development store" option then the issue of select the account to continue will appear.
In normal mode of the browser it will directed to the oAuth page.
because of this reason the review team rejected the app.
Server.js
import "#babel/polyfill";
import dotenv from "dotenv";
import "isomorphic-fetch";
import createShopifyAuth, { verifyRequest } from "#shopify/koa-shopify-auth";
import Shopify, { ApiVersion } from "#shopify/shopify-api";
import Koa from "koa";
import next from "next";
import Router from "koa-router";
dotenv.config();
const port = parseInt(process.env.PORT, 10) || 8081;
const dev = process.env.NODE_ENV !== "production";
const app = next({
dev,
});
const handle = app.getRequestHandler();
Shopify.Context.initialize({
API_KEY: process.env.SHOPIFY_API_KEY,
API_SECRET_KEY: process.env.SHOPIFY_API_SECRET,
SCOPES: process.env.SCOPES.split(","),
HOST_NAME: process.env.HOST.replace(/https:\/\/|\/$/g, ""),
API_VERSION: ApiVersion.October20,
IS_EMBEDDED_APP: true,
// This should be replaced with your preferred storage strategy
SESSION_STORAGE: new Shopify.Session.MemorySessionStorage(),
});
// Storing the currently active shops in memory will force them to re-login when your server restarts. You should
// persist this object in your app.
const ACTIVE_SHOPIFY_SHOPS = {};
app.prepare().then(async () => {
const server = new Koa();
const router = new Router();
server.keys = [Shopify.Context.API_SECRET_KEY];
server.use(
createShopifyAuth({
async afterAuth(ctx) {
// Access token and shop available in ctx.state.shopify
const { shop, accessToken, scope } = ctx.state.shopify;
const host = ctx.query.host;
ACTIVE_SHOPIFY_SHOPS[shop] = scope;
const response = await Shopify.Webhooks.Registry.register({
shop,
accessToken,
path: "/webhooks",
topic: "APP_UNINSTALLED",
webhookHandler: async (topic, shop, body) =>
delete ACTIVE_SHOPIFY_SHOPS[shop],
});
if (!response.success) {
console.log(
`Failed to register APP_UNINSTALLED webhook: ${response.result}`
);
}
// Redirect to app with shop parameter upon auth
ctx.redirect(`/?shop=${shop}&host=${host}`);
},
})
);
const handleRequest = async (ctx) => {
await handle(ctx.req, ctx.res);
ctx.respond = false;
ctx.res.statusCode = 200;
};
router.post("/webhooks", async (ctx) => {
try {
await Shopify.Webhooks.Registry.process(ctx.req, ctx.res);
console.log(`Webhook processed, returned status code 200`);
} catch (error) {
console.log(`Failed to process webhook: ${error}`);
}
});
router.post(
"/graphql",
verifyRequest({ returnHeader: true }),
async (ctx, next) => {
await Shopify.Utils.graphqlProxy(ctx.req, ctx.res);
}
);
router.get("(/_next/static/.*)", handleRequest); // Static content is clear
router.get("/_next/webpack-hmr", handleRequest); // Webpack content is clear
router.get("(.*)", async (ctx) => {
const shop = ctx.query.shop;
// This shop hasn't been seen yet, go through OAuth to create a session
if (ACTIVE_SHOPIFY_SHOPS[shop] === undefined) {
// const redirectUri = process.env.HOST + '/auth/callback';
// ctx.redirect(`https://${shop}/admin/oauth/authorize? //client_id=${process.env.SHOPIFY_API_KEY}&scope=${process.env.SCOPES}&state=$//{nonce}&redirect_uri=${redirectUri}`);
ctx.redirect(`/auth?shop=${shop}`);
} else {
await handleRequest(ctx);
}
});
server.use(router.allowedMethods());
server.use(router.routes());
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`);
});
});
If you guys can share your thoughts on this it will be very helpful.
Thanks.

add API key to url

Hi I'm build a wildfire app tracker with react using the nasa API it works in development by using the url directly witch is https://eonet.sci.gsfc.nasa.gov/api/v2.1/events
But when I deploy it. It does not get the data. I obviously need a api key witch I have, but how do I implement it in the url above ?
here is my code..
useEffect(() => {
const fetchEvents = async () => {
setLoading(true)
const res = await fetch('https://eonet.sci.gsfc.nasa.gov/api/v2.1/events')
const {events} = await res.json()
setEventData(events)
setLoading(false)
}
fetchEvents()
// eslint-disable-next-line
}, [])
You could try to create a .env file in which you can set URLS as
REACT_APP_PUBLIC_URL=https://eonet.sci.gsfc.nasa.gov/api/v2.1/events
and then in your app component import as
fetch(process.env.REACT_APP_PUBLIC_URL)

The resource <URL> was preloaded using link preload but not used within a few seconds from the window's load event - Wix fetch error

I'm using Google Analytics API to query user account and view
to do so, I'm using multiple WIX fetch functions (each fetch function depends on the previous one), here is one of them:
export function GetGAView (access_token, account_id,webPropertyId){
const url1 = "https://www.googleapis.com/analytics/v3/management/accounts/"
const url2 = account_id
const url3 = "/webproperties/"
const url4 = webPropertyId
const url5 = "/profiles?oauth_token="
const url6 = access_token
const url =url1.concat(url2,url3,url4,url5,url6).toString()
console.log(url, 'view url')
return fetch(url, {"method": "get"})
.then( (httpResponse) => {
if (httpResponse.ok) {
return httpResponse.json();
} else {
return Promise.reject("Fetch did not succeed");
}
} )
.then(json => {//console.log(json)
return json
}
)
.catch(err => console.log(err));
}
4 of 11 working well (same function distinguished by account id and properties id)and 7 functions return the following error shown on the console :
The error
/ga/oauth2callback?code=4%2XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&scope=email+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fanalytics&authuser=0&prompt=none:1 **The resource https://static.parastorage.com/services/editor-elements/dist/componentSdks.a8951fd0.bundle.min.js was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally.**
What does this error mean? How to solve this issue?
The only place I found the same error is here
https://www.wix.com/corvid/forum/community-discussion/parastorage-link-preload-failure

koa session expire event

Am trying to log a message when a koa session expires. But adding a listener for the expire event doesnt seem to work for me.
Following is the sample code. Set 2 mins as maxAge for the session.
import koa from 'koa';
import serve from 'koa-static';
import route from 'koa-route';
import session from 'koa-session';
import mount from 'koa-mount';
let pub = new koa();
let parse = new koa();
let app = new koa();
app.keys = ['test'];
const CONFIG = {
key: 'sess',
maxAge: 2000
};
parse.use(ctx => {
// ignore favicon
if (ctx.path === '/test') return;
let n = ctx.session.views || 0;
ctx.session.views = ++n;
ctx.body = n + ' views';
console.log(ctx.session);
});
pub.use(serve('./public'));
app.use(session(CONFIG,app));
app.on('expired',(key,value,ctx) => console.log(key));
app.use(mount('/',pub));
app.use(mount('/parse',parse));
app.listen(8080);
Here everytime i refresh the page after 2 seconds in browser i can see the "views" value set back to 1 meaning the previous session had expired. But the log statement as part of the expired event is not getting hit. May be the way am adding the event listener is wrong. Can someone please help?
After having a look at library files, koajs/session -> context.js
if (value._expire && value._expire < Date.now()) {
debug('expired session');
this.emit('expired', { key, value, ctx });
return false;
}
where emit is:
emit(event, data) {
setImmediate(() => {
this.app.emit(`session:${event}`, data);
});
}
So I think in your code you shouldchange the name you are trying to capture the event with:
app.on('session:expired',(key,value,ctx) => console.log(key));
If key is containing a value, you should see something printing out in the console :)

Resources