skip to Main Content

Is it possible to disable ssr on some pages using Next js? For example, I have a page with a product description on which I use ssr for SEO but I also have a page with a list of items or products which I can filter and for that page, I don’t want to use ssr because this page generates dynamically every time, how can I disable ssr on this page?

9

Answers


  1. Lazy load the component and disable SSR: https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr

    import dynamic from 'next/dynamic'
    
    const DynamicComponentWithNoSSR = dynamic(() => import('../components/List'), {
      ssr: false
    })
    
    export default () => <DynamicComponentWithNoSSR />
    
    Login or Signup to reply.
  2. This is a late answer, but in case anyone runs into this:

    const isServer = () => typeof window === `undefined`;
    
    const Page = () => isServer() ? null : (
    
      <> 
          <YourClientSideComponent />
      </>
    );
    

    This is on the “page” level. isServer() prevents rendering of anything while on the server side. You could, if you wanted to, prevent ssr on the component level also:

    const isServer = () => typeof window === `undefined`;
    
    const Page = () =>(
    
      <> 
          { !isServer() && <YourClientSideComponent /> }
      </>
    );
    
    Login or Signup to reply.
  3. The dynamic() function can also be used without a dynamic import:

    // components/NoSsr.jsx
    
    import dynamic from 'next/dynamic'
    import React from 'react'
    
    const NoSsr = props => (
      <React.Fragment>{props.children}</React.Fragment>
    )
    
    export default dynamic(() => Promise.resolve(NoSsr), {
      ssr: false
    })
    

    Anything wrapped in this component will not be visible in the SSR source. For example:

    // inside the page you want to disable SSR for
    
    import NoSsr from "components/NoSsr";
    
    Contact me at <NoSsr>[email protected]</NoSsr>
    
    Login or Signup to reply.
  4. Here’s a solution that i just came up with based on the something mentioned in the React docs: https://reactjs.org/docs/react-dom.html#hydrate

    class ClientOnly extends React.Component {
      state = {
        isClient: false,
      };
    
      componentDidMount() {
        this.setState({
          isClient: true,
        });
      }
    
      render() {
        const { isClient } = this.state;
        const { children } = this.props;
    
        return isClient ? children : false;
      }
    }
    

    You can then wrap any component / block with this and it won’t get rendered on the server. e.g.

    <ClientOnly>You're logged in as {name}</ClientOnly>
    

    This also prevents the following React.hydrate warning "Warning: Expected server HTML to contain a matching in ."

    Login or Signup to reply.
  5. We can also use react-no-ssr React component.

    Let’s say Comments is our client only component. Now we need to render it only on the client. Here’s how we do it.

    import React from 'react';
    import NoSSR from 'react-no-ssr';
    import Comments from './comments.jsx';
    
    const MyPage = () => (
      <div>
        <h2>My Blog Post</h2>
        <hr />
        <NoSSR>
          <Comments />
        </NoSSR>
      </div>
    );
    
    Login or Signup to reply.
  6. Another and I believe the simplest solution is to just use process.browser, which will only be true when ran on client side.

    <div>
      {
        process.browser && <Hidden />
      }
    </div>
    
    Login or Signup to reply.
  7. Put this on your _app.tsx

    import type { AppProps } from "next/app";
    import dynamic from "next/dynamic";
    import React from "react";
    
    const App = ({ Component, pageProps }: AppProps) => {
      return <Component {...pageProps} />;
    };
    
    export default dynamic(() => Promise.resolve(App), {
      ssr: false,
    });
    
    Login or Signup to reply.
  8. In @refactor answer, the react-no-ssr is not working for some typescript issue.

    I just wrote a very simple NoSSR component as below:

    import { ReactNode, useEffect, useLayoutEffect, useState } from 'react'
    
    const DefaultOnSSR: React.FC = () => null
    
    export const NoSSR: React.FC<{ children: ReactNode; onSSR?: ReactNode }> = ({ children, onSSR = <DefaultOnSSR /> }) => {
      const [onBrowser, setOnBrowser] = useState(false)
      useLayoutEffect(() => {
        setOnBrowser(true)
      }, [])
      return <>{onBrowser ? children : onSSR}</>
    }
    
    

    and can be used anywhere if you want to avoid SSR like below:

    const MyPage = () => (
      <div>
        <h2>My Blog Post</h2>
        <hr />
        <NoSSR>
          <Comments />
        </NoSSR>
      </div>
    );
    
    Login or Signup to reply.
  9. Based entirly on the answer by Erik Hofer, you can create an HOC to wrap your pages or other components in.

    import dynamic from 'next/dynamic';
    import React from 'react';
    
    const withNoSSR = (Component: React.FunctionComponent) => dynamic(
        () => Promise.resolve(Component),
        { ssr: false },
    );
    
    export default withNoSSR;
    

    Then use as:

    import React from 'react';
    import withNoSSR from './withNoSSR';
    
    function SomePage() {
        return (
            <div>Only renders in the browser</div>
        );
    }
    
    // wrap with HOC on export
    export default withNoSSR(SomePage);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search