skip to Main Content

I have a component in Nextjs AddressPage and I want to take advantage of Nextjs SSR to display all my HTML in page source using getServerSideProps.

In the getServerSideProps I am calling an API to fetch the addresses and the API needs access_token to be passed, and access_token is stored in local storage.

What is the best implementation to fetch access to local storage for the access_token?

access_token is set while the login API is called before fetching addresses.

Here are my codes:

AddressPage.component.tsx:

import React, { useState, useEffect } from "react";
import { get } from "@/services/http-apis";


const AddressPage = ({ addressListSSR, addressListSSR }: any) => {
  return (
    <div>{addressListSSR}-{addressListSSR}</div>
  );
};

export const getServerSideProps = async (context: any) => {
  const isUserLoggedInSSR = true;
  let addressListSSR = [];

    try {
      let res = await get(`/api/v1/address`);
      addressListSSR = res?.data || [];
    } catch (error) {
      console.error("RESPONSE Error:", error);
    }

  return {
    props: {
      addressListSSR,
      isUserLoggedInSSR,
    },
  };
};


export default AddressPage;

http-apis.js:

import { api } from "../config/config";
const { baseURL: BASE_URL } = api;


export const get = async (url = {}) => {
  try {
    const URL = `${BASE_URL}${url}`;
    const ISSERVER = typeof window === "undefined";
    console.log("ISSERVER:", ISSERVER);
    let auth = "{}";
    if (!ISSERVER) {
      auth = localStorage.getItem("auth");

      const { access_token } = JSON.parse(auth || {}) || {};

      const headers = {
        "Content-Type": "application/json",
      };

      if (access_token) {
        headers["Authorization"] = `Bearer ${access_token}`;
      }

      const response = await fetch(URL, {
        method: "GET",
        mode: "cors",
        headers,
      });
      return response;
    } else {
      console.log("Cant use local storage in SSR");
      return undefined;
    }
  } catch (error) {
    throw error;
  }
};

When I am calling API /api/v1/address, it fails because this API need an access token and we can not use local storage in the SSR context. but I need token anyhow to pass in the API.

What can I change in the code to achieve the same? any kind of support will be appreciated

2

Answers


  1. you cant access local storage from the server because local storage is in user’s browser
    you should use cookies to store your token
    cookies is something that can be a access in client side and server side

    Login or Signup to reply.
  2. You can’t access localStorage in the Node.js‘s environment. One of the standard methods for persisting some data across server and client environments in Next.ts is to use cookies.

    Here are the changes you need to make to use cookies instead of localStorage:

    1. Set the access_token in the cookies after a user logged in successfully
    2. Retrieve the access_token from cookies in getServerSideProps:
    import React, { useState, useEffect } from "react";
    import Cookies from 'cookies';
    import { get } from "@/services/http-apis";
    
    const AddressPage = ({ addressListSSR, isUserLoggedInSSR }) => {
      return (
        <div>{addressListSSR.join(', ')}</div>
      );
    };
    
    export const getServerSideProps = async (context) => {
      const cookies = new Cookies(context.req, context.res);
      const access_token = cookies.get('access_token');
      let addressListSSR = [];
      const isUserLoggedInSSR = !!access_token;
    
      if (isUserLoggedInSSR) {
        try {
          let res = await get(`/api/v1/address`, access_token);
          addressListSSR = res?.data || [];
        } catch (error) {
          console.error("RESPONSE Error:", error);
        }
      }
    
      return {
        props: {
          addressListSSR,
          isUserLoggedInSSR,
        },
      };
    };
    
    export default AddressPage;
    
    1. Modify your get function to accept the access_token as an argument(or retrieve the access token inside the function instead of passing it as an argument)
    import { api } from "../config/config";
    const { baseURL: BASE_URL } = api;
    
    export const get = async (url = {}, access_token) => {
     try {
       const URL = `${BASE_URL}${url}`;
       const headers = {
         "Content-Type": "application/json",
       };
    
       if (access_token) {
         headers["Authorization"] = `Bearer ${access_token}`;
       }
    
       const response = await fetch(URL, {
         method: "GET",
         mode: "cors",
         headers,
       });
       return response.json();
     } catch (error) {
       throw error;
     }
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search