How do I get the next-auth session with getStaticPaths and getStaticProps in dynamic routing?

Viewed 1321

I'm trying to implement dynamic routing in a NextJS app. I need the token from next-auth to get the data from getReport and getReports (in /reports.js) via an axios request to an API, but I don't know how to get it. It works when I try it with the token hard coded in [itemId].js, so the routing is working fine (I think).

Since getStaticPaths and getStaticProps runs on the server, I tried using getSession(), but I'm not sure if it doesn't work or I didn't used it correctly, but I could never get the session. Using getSession() would be the preferable option for me.

I also tried saving it in localStorage, but getStaticProps can't access localStorage.

I'm thinking of using Redux, but I'd really like to avoid it.

Here is my code:

/pages/user/reports/[reportId]/[itemId].js

import { useSession } from "next-auth/react";
import { useLayoutEffect } from "react";
import Loading from "../../../../components/Loading";
import Layout from "../../../../components/user/layout/Layout";
import { getAllReportsIds, getReportItem } from "../../../../components/user/reports";

const token = 'here is currently the token'

export default function Report({ reportItem }) {
  return (
    <Layout>
      {/* Start Page Header */}
      <div className="page-header">
      <h1 className="title">{ reportItem.name }</h1>
        <ol className="breadcrumb">
          <li className="active">{ reportItem.description }</li>
        </ol>
      </div>
      {/* End Page Header */}

      {/* START CONTAINER */}
      <div className="container-padding">

        {/* Start Row */}
        <div className="row">

          {/* Start Panel */}
          <div className="col-md-12">
            <div className="panel panel-default">
              
              <div className="panel-body">
                <div className="embed-responsive embed-responsive-16by9">
                  <iframe title="Reporte" className="embed-responsive-item" src={reportItem.code} allowFullScreen></iframe>
                </div>
              </div>
              
            </div>
          </div>
          {/* End Panel */}
        
        </div> 
        {/* End Row */}

      </div>
      {/* END CONTAINER */}
    </Layout>
  )
}

export async function getStaticPaths() {
  const paths = await getAllReportsIds(token)
  return {
    paths,
    fallback: false
  }
}

export async function getStaticProps(context) {
  console.log('context en static props: ', context)
  try {
    const reportItem = await getReportItem(token, context.params.reportId, context.params.itemId)
    return {
      props : {
        reportItem
      }
    }
  } catch(error) {
    console.log('error: ', error)
    return {
      props : {
        error: true
      }
    }
  }  
}

/components/user/reports.js

import { getReport, getReports } from "../../pages/api/axios/reports";

export async function getAllReportsIds(token) {
  try {
    const { data } = await getReports(token)
    let reportIds = []
    reportIds = data.flatMap(report => {
      return (
        report.report_items.map(item => {
          return {
            params: {
              reportId: JSON.stringify(report.id),
              itemId: JSON.stringify(item.id)
            }
          }
        })
      )
    })
    return reportIds
  } catch(error) {
    console.log('error: ', error)
  }
}

export async function getReportItem(token, reportId, itemId) {
  try {
    const { data } = await getReport(token, reportId)
    let reportItem = {}

    data.report_items.map(item => {
      if (JSON.stringify(item.id) === itemId) {
        reportItem = item
      }
    })
    return reportItem
  } catch(error) {
    console.log('error: ', error)
  }
}

If anyone can help, it would be really appreciated.

1 Answers

For some reason I thought I needed to use getStaticPaths, but I was getting the path from context.params, so I solved it by just removing that function and using getServerSideProps (like Mentlegen mentioned).

export async function getServerSideProps(context) {
  const session = await getSession(context)
  try {
    const reportItem = await getReportItem(session.token, context.params.reportId, context.params.itemId)
    return {
      props : {
        reportItem
      }
    }
  } catch(error) {
    console.log('error: ', error)
    return {
      props : {
        error: true
      }
    }
  }  
}
Related