Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass data to getServerSideProps from previous page in NextJS

I am developing an e-commerce like website using NextJS.

I will fetch & display list of products in /products page. On clicking any product, I'll navigate to /details/[productId], and I'll fetch those product details as follows.

// In /details/[productId].js file

export async function getServerSideProps({params}) {
    const res = await fetch(`https:my-api-url/api/products/${params.productId}`)
    const product = await res.json()
    return {
        props: {
            product
        }
    }
}

Problem

Everything looks good till this step. But I thought to reduce number of database read count, hence instead of fetching product detail again in detail page, I planned to use the data fetched in the previous page (/products) which will have the information about the product. Hence I need a way to pass those product object into next screen /details/[productId]'s getServerSideProps (to achieve SSR for SEO purposes).

Workaround

One solution I currently have is to stringify the product json and pass it via query parameter and get it back in getServerSideProps({params, query}). But it just spams my url in the browser which isn't look good at all.

Expectation

Is there any other way to pass the data into getServerSideProps function so that it will utilize the data to generate the whole page in server itself. Please guide me to overcome this issue. Any help would be appreciated.

Thanks in advance.. (:

like image 754
Ganesh Avatar asked Apr 25 '20 17:04

Ganesh


1 Answers

You can bring in a custom server as express that provides locals property available through the lifetime of your application or request.

const next = require('next');
const express = require('express');

const app = next({ dev: process.env.NODE_ENV !== 'production' });
const handle = routes.getRequestHandler(app);
const env = process.env.NODE_ENV || 'dev';


app.prepare().then(() => {
  const server = express();
   
  server.get('/products', async (req, reply) => {
    const products = await //... fetch product with details
    req.app.locals.products =  products;
    return app.render(req, reply, '/path/to/products/page', req.query);
  });
  
  server.get('/details/:productId', async (req, reply) => {
    const {productId} = req.params;
    const {products} = req.app.locals;
    // find product using productId and make available in req.locals
    req.locals.product = // product;
    return app.render(req, reply, '/path/to/product/detail/page', req.query)
  }); 
  
  server.get('*', (req, reply) => {
    return handle(req, reply)
  });

  server.listen(3000);
});

Pay caution to how large your product list grow to avoid running your application out of memory.

You could also return a cookie containing the list of products on the request for products (See limits for HTTP cookies). Then read that on the product detail page.

like image 154
Oluwafemi Sule Avatar answered Sep 28 '22 04:09

Oluwafemi Sule