Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Technical Debt: state of the product is lost on refresh in Product Page #1

Closed
DragonSenses opened this issue Jun 15, 2023 · 1 comment
Assignees
Labels
bug Something isn't working

Comments

@DragonSenses
Copy link
Owner

DragonSenses commented Jun 15, 2023

In the current version, when a user hits refresh on a product page they lose access to the state. The correct behavior should be that on refresh, the user should generally get back to the same state.

The stop-gap solution in /app/product/page.js:

export default function ProductPage(props) {
  const { searchParams } = props;
  const product = useCart(state => state.product);

  if(!product?.name){
    window.location.href = '/';
  }

// ...

This is a technical debt, as currently it checks that if we do not have access to the product.name (through optional chaining).

If we do not have access to the product's name, consequently we also do not have access to the product. This is a way to check if state is lost on page refresh.

Issue: how this is handled

The issue is that we simply re-route the user back to the home route (re-navigate them to the home page) in this scenario.

The problem with this is if users wish to share URLs to products, they wouldn't be able to. Other users cannot share other product URLS because they do not have access to the product state. They would have to access the specific product by clicking on its ProductCard on the home-page.

@DragonSenses DragonSenses self-assigned this Jun 15, 2023
@DragonSenses DragonSenses added the bug Something isn't working label Jun 15, 2023
@DragonSenses DragonSenses pinned this issue Jun 18, 2023
@DragonSenses
Copy link
Owner Author

Solution: Refetch the product on page load on the sub page route

Instead of loading product from the state

  /* Load product from state */
  let product = useCart(state => state.product);

We can refetch the product on page load on the sub-page route (product page).

The state will always be there. So users can now share URLs to products or even refresh the page.

Convert Product Page to async

export default async function ProductPage(props) {
  const { searchParams } = props;
  const { price_id } = searchParams;

Create the fetch function to load product

Create loadProduct() which fetches the product on page-load.

  async function loadProduct(id){
    const lineItems = {
      price_id: id,
    }

    const response = await fetch('/api/price', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ lineItems })
    });

    const data = await response.json();

    return data;
  }

Create the route that returns the price object for the specific product

Note: how the filtering happens within the POST Route Handler rather than the client-side product page to improve load times.

import { NextResponse } from "next/server";
import Stripe from "stripe";

export async function POST(request) {
  const body = await request.json();

  if(body.lineItems.length === 0){
    return new Response('Error', {
      status: 405,
    });
  }

  // Destructure out price_id from the request body
  const { price_id } = body.lineItems;

  try{
    // Initialize Stripe
    const stripe = new Stripe(process.env.STRIPE_SECRET ?? '', {
      apiVersion: '2020-08-27'
    });

    // Fetch a list of prices
    const res = await stripe.prices.list({
      expand: ['data.product']
    });

    console.log(res);

    // Access price list data within the response (an array)
    const dataArr = res.data;

    // Filter through by price_id
    const price = dataArr.filter(item => item.id === price_id);

    return NextResponse.json({ price });

  } catch(err) {
    console.log("-------- error on product page load --------");
    console.log(err);
    return new Response('Error', {
      status: 500,
    });
  }
}

Back to the Product Page

Load the product in, access the data, and destructure the information we need to dynamically render the sub-page:

  /* Fetch product on page load */
  const price = await loadProduct(price_id);
  
  const product = price.price[0];

  const {
    unit_amount: cost,
    product: productInfo,
  } = product;

  const {
    name,
    description
  } = productInfo;

Remove the check that routes users back to the home page

  // If product does not exist, bring user to home-page
  // if(!product?.name){
  //   window.location.href = '/';
  // }

Successfully load the product page

With these changes, users can now:

  • Share URLs to products and access other product pages
  • Refresh the page
  • Stay on the product page, without being irritably re-routed to the home page

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant