'How to get global.window.localStorage inside getServerSideProps

I have some component which get props with data and render it data. In my getServerSideProps function I need to get data from localStorage, but I can't do it because of window is undefined.

I tried using if (typeof window !== 'undefined') but it's still not working. What's wrong with my code?

const MainComponent = ({serverResponseData}) => {
  // ... some code
  console.log(serverResponseData))
  // ... some code
}

export async function getServerSideProps() {
  let filterId = []

  if (typeof window !== 'undefined') {
    filterId = global.window?.localStorage.getItem('filterId') || '';
  }

  // ...some code, and filterId variable still empty array
  const scoresRes = await fetchData('scores',{filterId});

  return {
    props: {scoresRes}
  };
}

I'm also tried use useEffect, but got error

React Hook "useEffect" is called in function "getServerSideProps" that is neither a React function component nor a custom React Hook function.



Solution 1:[1]

Referring to the documentation

If you export a function called getServerSideProps (Server-Side Rendering) from a page, Next.js will pre-render this page on each request using the data returned by getServerSideProps.

Localstorage is only available on the client side and you are trying to access it in a server side only function , you can use something like

if (typeof window !== 'undefined') {
// your code 
  const id = query.id;
    const getData = JSON.parse(localStorage.getItem("form"));
    console.log(getData)
}

Please review this article to get more information on running client side only code.

Another approach would be to use a dynamic import where the hello3 component would contain the code accessing local storage.

import dynamic from 'next/dynamic'

const DynamicComponentWithNoSSR = dynamic(
  () => import('../components/hello3'),
  { ssr: false }
)

function Home() {
  return (
    <div>
      <Header />
      <DynamicComponentWithNoSSR />
      <p>HOME PAGE is here!</p>
    </div>
  )
}

export default Home

Solution 2:[2]

getServerSideProps only trigger on the server-side and it won't be available on the client-side

getServerSideProps only runs on server-side and never runs on the browser.

If you want to have that storage logic, I'd suggest you use cookies instead. Not like localStorage, cookies are available on both server-side and client-side.

You can modify your logic like below with cookies

export async function getServerSideProps(context) {
  const filterId = context.req.cookies.filterId || ''; //get filterId from cookies

  // ...some code, and filterId variable still empty array
  const scoresRes = await fetchData('scores',{filterId});

  return {
    props: {scoresRes}
  };
}

Another possible approach is using getInitialProps which is available on both sides

MainComponent.getInitialProps() {
  let filterId = []

  if (typeof window !== 'undefined') {
    filterId = global.window?.localStorage.getItem('filterId') || '';
  }

  // ...some code, and filterId variable still empty array
  const scoresRes = await fetchData('scores',{filterId});

  return scoresRes;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Krushnal Patel
Solution 2 Nick Vu