Home > Blockchain >  Difference(s) between getStaticPaths getStaticProps and useRouter in NextJS?
Difference(s) between getStaticPaths getStaticProps and useRouter in NextJS?

Time:07-18

I'm learning NextJS and currently I don't understand the differences, and when I should use getStaticProps & getStaticPaths compared to useRouter().query.

So far to me, it seems like they can do the same thing for my very simple book-listing site: getting the ID from the URL e.g: "localhost:3000/books/book1" and use that ID to fetch and display the corresponding item from a database (simulated with some async functions below)

These are my 2 approaches written in pages/books/[bookId].tsx, and they both work.

Using getStaticPaths, getStaticProps

export async function getStaticPaths() {
  const books: Book[] = await getBooksAsync();
  const paths = books.map((book) => {
    return { params: { bookId: book.id } };
  });

  return {
    paths,
    fallback: false,
  };
}

export async function getStaticProps(context: GetStaticPropsContext) {
  const params = context.params!;
  const bookId = params.bookId as string;
  const book = await getBookByIdAsync(bookId);

  return {
    props: {
      book,
    },
  };
}

const Book = ({ book }: { book: Book }) => {
  return (
    <div>
      <p>Book Id: {book.id}</p>
      <p>Title: {book.title}</p>
      <p>Year: {book.year}</p>
      <p>Reviews Count: {book.reviews.length}</p>
    </div>
  );
};

Using useRouter().query

const Book = () => {
  const router = useRouter();
  const query = router.query;
  const bookId = query.bookId as string;

  const [book, setBook] = useState<Book>();

  useEffect(() => {
    async function getBooks() {
      const _book = await getBookByIdAsync(bookId);
      setBook(_book);
    }

    getBooks();
  }, [bookId]);

  if (!book) return <></>;

  return (
    <div>
      <p>Book Id: {book.id}</p>
      <p>Title: {book.title}</p>
      <p>Year: {book.year}</p>
      <p>Reviews Count: {book.reviews.length}</p>
    </div>
  );
};

CodePudding user response:

The difference is when your code runs. The functions getStaticPaths and getStaticProps runs on compile time, i.e. when you run the command next build. This generates the HTML once, and no JS runs when someone visits your site to look at a book. The page will look the same for everyone.

The code with useRouter and useEffect, however, fetches the book data on page load. When someone visits your site their browser fetches the data, and then runs some JS to display the data to them.

The different approaches have different uses. If you frequently update book data and don't want to rebuild your site everytime some data changes, you may want to use useRouter and fetch the data on load. The downside is more requests to your server, and more waiting time for your users. However, you will ensure the displayed data is always up to date.

A combination of the two is often used as a middle ground. In this instance, assuming you control the server, you could for instance load the book data in getStaticProps, but fetch reviews dynamically on page load with useRouter.

CodePudding user response:

getStaticPaths and getStaticProps allows the webpage to be generated and rendered on the server, which leads to a faster content paint for the user. The router.query method fetches the data after the client gets the initial HTML and javascript, leading to a much slower content paint for the user. It also increases the amount of javascript the client will have to download because useRouter would have to be bundled in the javascript.

Additionally, you can't have dynamic routes in next.js without getStaticPaths.

Basically, just use getStaticPaths and getStaticProps, with the only exception being if the book data changes extremely quickly.

  • Related