loading...

6 tips: Using Next.js for your next web app

jlei523 profile image jlei523 ・4 min read

Next.js is indispensable when you want to build a high performance React app.

It’s being used to power some of my apps such as Medtally, a data-driven medical community and True Home, an automated home valuation tool for properties in Hong Kong.

Along the way, I learned a few tricks and figured out a few “gotchas” of the framework that beginners might find useful. And without further ado, let’s get started:

1. You need to cache the data from getInitialProps or the browser’s back button behavior will break.

getInitialProps is used to fetch data for the page but it also fires when the user presses the back button on the browser. This causes the browser to scroll to the position where you previously left off but without the remote data from getInitialProps needed to render. You can read more about this issue here.

To solve this problem, you need to cache the data on the client side after fetching it. Here’s a quick and simple way to do it:


let cache = {};

class App extends React.Component {
  static async getInitialProps({ req, query, asPath, pathname }) {

    let data;
    //if data is in cache then use the cache
    if (cache[someID]) {
      data = cache[someID]
    } else {
      //if not, then fetch from server
      data = await fetch(`someAPI`);
    }

    return {
     data: data
    }

  render() {
      //check if client, if so store the data in the cache. 
      //If you don't do this check, there will be a separate cache stored on the server since Next.js does server side rendering as well.
      if (process.browser) {
        cache[someID] = this.props.data;
      }

      render (){

       //your components
      }
    }
  }

You can also do this with Redux.

2. Use Next.js’ Link component instead of Router.push so Google can crawl your URLs

Google’s crawler doesn’t see links written like this: <div onClick={handleClickWithRouter}>Go to About Page!</div>

So avoid writing your links with Next’s Router if possible. Instead, use Next’s <Link> component like this:

import Link from 'next/link'

function Home() {
  return (
    <div>
      Click{' '}
      <Link href="/about">
        <a>here</a>
      </Link>{' '}
      to read more
    </div>
  )
}

export default Home

3. Next.js works better with Material UI React than Semantic UI React

If you’re trying to choose between Material UI and Semantic UI React component libraries to go along with your Next.js app, you should choose Material UI.

Semantic UI’s responsive components aren’t built in a way that works well with Next.js’ server-side rendering because they look for the browser’s window object which isn’t available on the server.

If you must use Semantic UI, you can hack it together by following this GitHub ticket.

On the other hand, Material UI’s responsive components only use media queries which means your components should render in the same way on the server and in the client.

If I convinced you, head over to Material UI’s Next.js example to get started.

4. If you use isomorphic-unfetch to do your data fetching, you’ll need to provide the absolute URL

The Next.js creators recommend a library called isomorphic-unfetch for data fetching. It has a much smaller bundle size than axios and works well on both the client and the server.

However, isomorphic-unfetch requires an absolute URL or it will fail. I’m assuming it has something to do with the different environments (client & server) on which your code can be executed. Relative URLs are just not explicit & reliable enough in this case.

You can construct an absolute URL from getInitialProps like this:

class App extends React.Component {
  static async getInitialProps({ req, query, asPath, pathname }) {

    let baseUrl = req ? `${req.protocol}://${req.get("Host")}` : "";

    let data = await fetch(baseUrl + 'relativeURL')


    return {
      data: data

    }

  }
  1. Store your URLs in the database if you want the prettiest of pretty URLs

URLs should be pretty so people want to click on them when they see them on Google.

You generally want to avoid having the database table id in your URL like this: /post/245/i-love-nextjs/.

Ideally, your URLs should be something like this: /post/i-love-nextjs.

But this URL is missing the id 245 needed to fetch the data from the database.

To solve this problem, you’ll need to store the URL in the database like this:

id title Content url
245 I love Next.js because... /post/i-love-nextjs

On the server, write code to fetch data using the URL in lieu of the post id when someone requests mywebsite.com/post/i-love-nextjs. Here’s an example using Express.js:

server.get('/post/:slug', async (req, res) => {
    const actualPage = "/post";

    //get the data using '/post/i-love-nextjs' as the id
    let data = await fetchDataWithURL(req.params.slug)

    const postContent = { data: data  };
    app.render(req, res, actualPage, postContent);
  });

I recommend slugify if you need a library to convert text into URLs.
If you have many URLs and you’re using a relational database, you should consider adding an index to the url column so that your lookup query runs faster.

  1. CSS breaks in prod but not development when using Material UI with Next.js
function createPageContext() {
  return {
    theme,
    sheetsManager: new Map(),
    sheetsRegistry: new SheetsRegistry(),


    //add this to fix broken css in prod
    generateClassName: createGenerateClassName({
      productionPrefix: "prod"
    })


  };
}

If this happens to you, try adding this line to your getPageContext.js file:

And that’s it!

Posted on by:

jlei523 profile

jlei523

@jlei523

Creator @ http://Medtally.com, a new way for patients to connect and share. Also made http://truehome.hk. Ex @Redfin & @Rocketlawyer

Discussion

pic
Editor guide
 

Good article, dude. I'm new into nextJS, so this was pretty helpful.

About the last one 'createPageContext()', it should be added on my _document.js?