-
-
Save whoisryosuke/d034d3eaa0556e86349fb2634788a7a1 to your computer and use it in GitHub Desktop.
Ive been having trouble getting a HOC to work like this for pages that use getStaticProps. Any suggestions ?
Thanks man, it helped me alot.
Ive been having trouble getting a HOC to work like this for pages that use getStaticProps. Any suggestions ?
Thanks for this! Do you have an example that uses the new getServerSideProps() implementation?
Haven't tested this yet but would it be just like dealing with getInitialProps
?
static async getServerSideProps(ctx) {
// Check if Page has a `getServerSideProps`; if so, call it.
const pageProps = AuthComponent.getServerSideProps && await AuthComponent.getServerSideProps(ctx);
// Return props.
return { ...pageProps }
}
Ive been having trouble getting a HOC to work like this for pages that use getStaticProps. Any suggestions ?
Thanks for this! Do you have an example that uses the new getServerSideProps() implementation?
Haven't tested this yet but would it be just like dealing with
getInitialProps
?static async getServerSideProps(ctx) { // Check if Page has a `getServerSideProps`; if so, call it. const pageProps = AuthComponent.getServerSideProps && await AuthComponent.getServerSideProps(ctx); // Return props. return { ...pageProps } }
Unfortunately, this doesn't work because new versions of next now require that getServerSideProps
and getStaticProps
be exported like so:
export const getStaticProps = () => ({
props: {
hello: 'world',
},
})
The solution proposed would result in an error similar to this -> Error: page /profile getServerSideProps can not be attached to a page's component and must be exported from the page. See more info here: https://err.sh/next.js/gssp-component-member
. I'm also in need of a solution and am working on one. Will let you'll know if I come up with something.
@othneildrew Did you ever resolve this? I have hit a similar problem here. auth0/nextjs-auth0#148
Hi, I've just realized, why don't we use this withAuth
as a HOC on the component that the page renders, not on the page itself. This way we could use getStaticProps
and getServerSideProps
as normal.
The withAuth
HOC will then only be responsible for authentication check and redirect stuff, no need for getIntitalProps
inside since we could declare that on the page.
For example, a page at pages/products.js
import React from 'react'
import ProductList from '@components/ProductList'
import withAuth from '@utils/withAuth'
function ProductsPage(props) {
const AuthenticatedProductList = withAuth(ProductList);
return <AuthenticatedProductList {...props} />
}
export async function getStaticProps(context) {
// getStaticProps stuff
}
export async function getServerSideProps(context) {
// getServerSideProps stuff
}
ProductsPage.getInitialProps = async (ctx) => {
// getInitialProps stuff
}
export default ProductsPage;
Hi, I've just realized, why don't we use this
withAuth
as a HOC on the component that the page renders, not on the page itself. This way we could usegetStaticProps
andgetServerSideProps
as normal.
ThewithAuth
HOC will then only be responsible for authentication check and redirect stuff, no need forgetIntitalProps
inside since we could declare that on the page.
For example, a page atpages/products.js
import React from 'react' import ProductList from '@components/ProductList' import withAuth from '@utils/withAuth' function ProductsPage(props) { const AuthenticatedProductList = withAuth(ProductList); return <AuthenticatedProductList {...props} /> } export async function getStaticProps(context) { // getStaticProps stuff } export async function getServerSideProps(context) { // getServerSideProps stuff } ProductsPage.getInitialProps = async (ctx) => { // getInitialProps stuff } export default ProductsPage;
can you provide a full implementation please?
I couldn't use the getServerSideProps
method in a HOC, because it is only available on pages. Neither use getInitialProps
inside a getServerSideProps
, I got a warning in my console.
In my case. I needed a generic function to validate the user's access to a private page with an async call. I solved this by creating a function that receives the context and a callback.
//util.js
const validateRoute = (context) => async (callback) => {
const { id, pathname } = context.query;
const paths = await getAllowedPaths(id);
if (!paths.includes(pathname)) {
return {
redirect: "/home",
permanente: false,
};
}
return callback();
};
In all my private pages.
export const getServerSideProps = (context) => {
return validateRoute(context)(async () => {
// my custom callback for each page.
const { id } = context.query;
const props = await getUserData(id);
return {
props,
};
});
};
I couldn't use the
getServerSideProps
method in a HOC, because it is only available on pages. Neither usegetInitialProps
inside agetServerSideProps
, I got a warning in my console.In my case. I needed a generic function to validate the user's access to a private page with an async call. I solved this by creating a function that receives the context and a callback.
//util.js const validateRoute = (context) => async (callback) => { const { id, pathname } = context.query; const paths = await getAllowedPaths(id); if (!paths.includes(pathname)) { return { redirect: "/home", permanente: false, }; } return callback(); };In all my private pages.
export const getServerSideProps = (context) => { return validateRoute(context)(async () => { // my custom callback for each page. const { id } = context.query; const props = await getUserData(id); return { props, }; }); };
would you help port this to typescript?
I was able to cast it like this:
import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next'
import Cookies from 'cookies'
type EmptyProps = {
props: Record<string, unknown>
}
// HOC to only be executed when user is not logged in, otherwise redirect to portal
const withoutAuth = (context: GetServerSidePropsContext) => async (
callback: () => any
): Promise<GetServerSidePropsResult<EmptyProps>> => {
const cookies = new Cookies(context.req, context.res)
if (cookies.get('user')) {
return {
redirect: {
destination: '/protected-source',
permanent: false,
},
}
}
return callback()
}
export default withoutAuth
I still can't figure the typescript definition for the callback... I've ended up doing callback: () => any
I couldn't use the
getServerSideProps
method in a HOC, because it is only available on pages. Neither usegetInitialProps
inside agetServerSideProps
, I got a warning in my console.
In my case. I needed a generic function to validate the user's access to a private page with an async call. I solved this by creating a function that receives the context and a callback.//util.js const validateRoute = (context) => async (callback) => { const { id, pathname } = context.query; const paths = await getAllowedPaths(id); if (!paths.includes(pathname)) { return { redirect: "/home", permanente: false, }; } return callback(); };In all my private pages.
export const getServerSideProps = (context) => { return validateRoute(context)(async () => { // my custom callback for each page. const { id } = context.query; const props = await getUserData(id); return { props, }; }); };would you help port this to typescript?
I was able to cast it like this:
import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next' import Cookies from 'cookies' type EmptyProps = { props: Record<string, unknown> } // HOC to only be executed when user is not logged in, otherwise redirect to portal const withoutAuth = (context: GetServerSidePropsContext) => async ( callback: () => any ): Promise<GetServerSidePropsResult<EmptyProps>> => { const cookies = new Cookies(context.req, context.res) if (cookies.get('user')) { return { redirect: { destination: '/protected-source', permanent: false, }, } } return callback() } export default withoutAuthI still can figure the typescript definition for the callback... I've ended up doing
callback: () => any
@mtoranzoskw callback
has no parameter and might return the same values of withoutAuth
. Try this out, let me know if it works.
const withoutAuth = (context: GetServerSidePropsContext) => async (
callback: () => GetServerSidePropsResult<EmptyProps>
): Promise<GetServerSidePropsResult<EmptyProps>> => {
I couldn't use the
getServerSideProps
method in a HOC, because it is only available on pages. Neither usegetInitialProps
inside agetServerSideProps
, I got a warning in my console.
In my case. I needed a generic function to validate the user's access to a private page with an async call. I solved this by creating a function that receives the context and a callback.//util.js const validateRoute = (context) => async (callback) => { const { id, pathname } = context.query; const paths = await getAllowedPaths(id); if (!paths.includes(pathname)) { return { redirect: "/home", permanente: false, }; } return callback(); };In all my private pages.
export const getServerSideProps = (context) => { return validateRoute(context)(async () => { // my custom callback for each page. const { id } = context.query; const props = await getUserData(id); return { props, }; }); };would you help port this to typescript?
I was able to cast it like this:import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next' import Cookies from 'cookies' type EmptyProps = { props: Record<string, unknown> } // HOC to only be executed when user is not logged in, otherwise redirect to portal const withoutAuth = (context: GetServerSidePropsContext) => async ( callback: () => any ): Promise<GetServerSidePropsResult<EmptyProps>> => { const cookies = new Cookies(context.req, context.res) if (cookies.get('user')) { return { redirect: { destination: '/protected-source', permanent: false, }, } } return callback() } export default withoutAuthI still can figure the typescript definition for the callback... I've ended up doing
callback: () => any
@mtoranzoskw
callback
has no parameter and might return the same values ofwithoutAuth
. Try this out, let me know if it works.const withoutAuth = (context: GetServerSidePropsContext) => async ( callback: () => GetServerSidePropsResult<EmptyProps> ): Promise<GetServerSidePropsResult<EmptyProps>> => {
Not working... I've tried that but I have an error when implementing it
Got an error using Promise as well (callback: () => Promise<GetServerSidePropsResult<EmptyProps>>
)
I couldn't use the
getServerSideProps
method in a HOC, because it is only available on pages. Neither usegetInitialProps
inside agetServerSideProps
, I got a warning in my console.
In my case. I needed a generic function to validate the user's access to a private page with an async call. I solved this by creating a function that receives the context and a callback.//util.js const validateRoute = (context) => async (callback) => { const { id, pathname } = context.query; const paths = await getAllowedPaths(id); if (!paths.includes(pathname)) { return { redirect: "/home", permanente: false, }; } return callback(); };In all my private pages.
export const getServerSideProps = (context) => { return validateRoute(context)(async () => { // my custom callback for each page. const { id } = context.query; const props = await getUserData(id); return { props, }; }); };would you help port this to typescript?
I was able to cast it like this:import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next' import Cookies from 'cookies' type EmptyProps = { props: Record<string, unknown> } // HOC to only be executed when user is not logged in, otherwise redirect to portal const withoutAuth = (context: GetServerSidePropsContext) => async ( callback: () => any ): Promise<GetServerSidePropsResult<EmptyProps>> => { const cookies = new Cookies(context.req, context.res) if (cookies.get('user')) { return { redirect: { destination: '/protected-source', permanent: false, }, } } return callback() } export default withoutAuthI still can figure the typescript definition for the callback... I've ended up doing
callback: () => any
@mtoranzoskw
callback
has no parameter and might return the same values ofwithoutAuth
. Try this out, let me know if it works.const withoutAuth = (context: GetServerSidePropsContext) => async ( callback: () => GetServerSidePropsResult<EmptyProps> ): Promise<GetServerSidePropsResult<EmptyProps>> => {Not working... I've tried that but I have an error when implementing it
Got an error using Promise as well (
callback: () => Promise<GetServerSidePropsResult<EmptyProps>>
)
@mtoranzoskw try to make your props
optional.
type EmptyProps = {
props?: Record<string, unknown>
}
// or
type EmptyProps = {
props: Partial<Record<string, unknown>>
}
Thanks for the help @Sergioamjr
I've tried both, but making props optional was the only one that worked! I guess Partial
would go 1 level up so that props become optional.
type EmptyProps = {
props?: Record<string, unknown>
}
💪
anyone done this without getInialProps ? currently im using next 11 and i want to add auth to my app but so far i couldnt understand the logic around protected routes in next js
Thank a lot
Thanks for this! Do you have an example that uses the new getServerSideProps() implementation?