How do I detect whether I am on server on client in next.js?
Asked Answered
A

6

152

I am using a customer express server with Next.js. It's running within a container. I am doing an http request with isomorphic-fetch to get data for my render. I'd like to do localhost when running on server and mysite.com when running on client. Not sure the best way to accomplish this. I can do it hackily by doing const isServer = typeof window === 'undefined' but that seems pretty bad.

Airmail answered 21/3, 2018 at 16:30 Comment(0)
D
294

Now (2020 Jan) it should be typeof window === 'undefined' since process.browser is deprecated

Refer to https://github.com/zeit/next.js/issues/5354#issuecomment-520305040

Drown answered 2/1, 2020 at 10:54 Comment(3)
Great answer! Adding a note, though, that if you're using Typescript and, like me, you get the error "cannot find name window", it is because you need to add "dom" to your lib array in tsconfig.json. For some reason Next.js doesn't include this by default.Toile
Client side also has worker thread scopes, where window is not defined. A keyword that is available in both the main browser thread and workers would be self, so the check could be typeof self === 'undefined'. On top of that, you can define a global named window or self on the server, which would invalidate this method.Thagard
Probably globalThis.window is the most flexible way on every environment? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Americana
A
76

You can use process.browser to distinguish between server environment (NodeJS) and client environment (browser).

process.browser is true on the client and undefined on the server.

Aftertime answered 21/3, 2018 at 17:5 Comment(3)
Also isServer is a thing, depending on the Next function call. I did need to use process.browser from where I needed the logic though :)Airmail
I think process.browser is added by webpack which then propagates to next.jsWildeyed
Please look at @kenberkeley's answer below instead of using this. process.browser is deprecated and using typeof window instead will get you in-framework optimizations.Toile
G
11

Since I don't like depending on odd third party things for this behavior (even though process.browser seems to come from Webpack), I think the preferred way to check is for presence of appContext.ctx.req like this:

async getInitialProps (appContext) {

    if (appContext.ctx.req) // server? 
    {
        //server stuff
    }
    else {
        // client stuff
    }
}

Source: https://github.com/zeit/next.js/issues/2946

Gunplay answered 15/8, 2019 at 0:46 Comment(2)
This assumes you are in getInitialProps or have access to appContextRenaerenaissance
I wouldn't use an obscure syntax for a basic concept - an isClient(appContext) helper would read much better.Sclerosis
C
6

Also, as variant, you can add variable to your .env file without NEXT_PUBLIC_ prefix.

Like as: IS_SERVER_FLAG=true

This variable will be available only on server side

And after, you can check it in your code

const isServer = process.env.IS_SERVER_FLAG ? 'RUN ON SERVER' : 'RUN_ON_CLIENT'

Clevey answered 28/9, 2023 at 12:27 Comment(0)
I
5

One additional note is that componentDidMount() is always called on the browser. I often load the initial data set (seo content in getInitialProps(), then load more in depth data in the componentDidMount() method.

Ive answered 24/7, 2018 at 0:27 Comment(2)
Is there a way to do this with the useEffect() hook?Proviso
@Proviso Yes, useEffect directly replaces componentDidMount (plus componentDidUpdate and componentWillUnmount all in one). If you just write useEffect(() => { .. }, []) then it's the exact equivalent. See reactjs.org/docs/hooks-effect.htmlMorin
A
-3

getServerSideProps and getStaticProps are added in Next 9.3(Mar 2020), and these functions are recommended.

If you're using Next.js 9.3 or newer, we recommend that you use getStaticProps or getServerSideProps instead of getInitialProps.

So no need to detect, just put server side stuff in getServerSideProps.

const MyPage = () => {
  useEffect(() => {
    // client side stuff
  }, [])

  return (
    <div> ... </div>
  )
}

MyPage.getServerSideProps = async () => {
  // server side stuff
}
Apterous answered 22/3, 2021 at 9:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.