Home > Software engineering >  react js: infinite page rendering issue
react js: infinite page rendering issue

Time:07-13

So I have a page in react that is constantly rendering , say for eg. when I console log I can see that getting logged infinitely in a loop. is it some hook on some inner components that is getting rendered constantly I can't figure out

When i comment out

 <CartContainer line_items = {line_items} />

it still doesnt solve the issue.

could useCartState() context be the issue?

Below is the page

import React, {useEffect} from "react"
import { CartContainer, NavigationBar } from "../components"
import {useRouter} from 'next/router'
import { useCartState } from "../context/Cart"
import { QuestionMarkCircleIcon } from '@heroicons/react/solid'

 
const  getPaymentAPIStatus = async () =>
 { 
      
     const response = await fetch("https://api.nowpayments.io/v1/status")
     
     const data = await response.json()
 }

 const CartPage = () => {
    const router = useRouter();

    const {line_items, subtotal, total_items} = useCartState() // to get cart details --anaya
    
    const isEmpty = line_items.length === 0
    


        if(isEmpty)
            return(
            <div>
                <NavigationBar/>
                <p>Your cart is empty. Please add some items</p>

            </div>
            )

        else {

     return(
            <div>
                <NavigationBar/>
                <div className="bg-white">
                <div className="max-w-2xl mx-auto pt-16 pb-24 px-4 sm:px-6 lg:max-w-7xl lg:px-8">
                    <h1 className="text-3xl font-extrabold tracking-tight text-gray-900 sm:text-4xl">Shopping Cart</h1>
                    <form className="mt-12 lg:grid lg:grid-cols-12 lg:gap-x-12 lg:items-start xl:gap-x-16">
                        <section aria-labelledby="cart-heading" className="lg:col-span-7">
                            <h2 id="cart-heading" className="sr-only">
                                Items in your shopping cart
                            </h2>

                            <CartContainer line_items = {line_items} />

            
                        </section>

                {/* Order summary */}
                        <section
                        aria-labelledby="summary-heading"
                        className="mt-16 bg-gray-50 rounded-lg px-4 py-6 sm:p-6 lg:p-8 lg:mt-0 lg:col-span-5"
                            >
                            <h2 id="summary-heading" className="text-lg font-medium text-gray-900">
                            Order summary
                            </h2>

                            <dl className="mt-6 space-y-4">
                            <div className="flex items-center justify-between">
                                <dt className="text-sm text-gray-600">Subtotal</dt>
                                <dd className="text-sm font-medium text-gray-900">{subtotal.formatted_with_symbol}</dd>
                            </div>
                            <div className="border-t border-gray-200 pt-4 flex items-center justify-between">
                                <dt className="flex items-center text-sm text-gray-600">
                                    <span>Shipping estimate</span>
                                    <a href="#" className="ml-2 flex-shrink-0 text-gray-400 hover:text-gray-500">
                                    <span className="sr-only">Learn more about how shipping is calculated</span>
                                    <QuestionMarkCircleIcon className="h-5 w-5" aria-hidden="true" />
                                    </a>
                                </dt>
                                <dd className="text-sm font-medium text-gray-900">Free</dd>
                            </div>
                            <div className="border-t border-gray-200 pt-4 flex items-center justify-between">
                                <dt className="text-base font-medium text-gray-900">Order total</dt>
                                <dd className="text-base font-medium text-gray-900">{subtotal.formatted_with_symbol}</dd>
                            </div>
                            </dl>

                            <div className="mt-6">
                             <button
                                type="submit"
                                className="w-full bg-indigo-600 border border-transparent rounded-md shadow-sm py-3 px-4 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-50 focus:ring-indigo-500"
                                >
                                Checkout
                                </button>
                            </div>

                
                            <div className="mt-6 text-sm text-center">
                            <p>
                                or{' '}
                                <a href ={`${router.basePath}/ChooseProduct`} className="text-indigo-600 font-medium hover:text-indigo-500">
                                Continue Designing<span aria-hidden="true"> &rarr;</span>
                                </a>
                            </p>
                            </div>

                        </section>
                    </form>
                 </div>
             </div>

              </div> 

            )
        }
}

export default CartPage


How do i solve this? Thanks in advance!

Adding useCartState as requested

import {createContext, useEffect, useContext, useReducer} from 'react'
import {commerce} from '../../lib/commerce'
//need to correct this file to be a tsx file in the future

//Provides a context for Cart to be used in every page

const CartStateContext = createContext()
const CartDispatchContext = createContext()

const SET_CART = "SET_CART"

const initialState = {
    total_items: 0,
    total_unique_items: 0,
    subtotal:[],
    line_items: [{}]
}


const reducer = (state,action) => {
    switch(action.type){
        case SET_CART:
            return { ...state, ...action.payload }
        default: 
            throw new Error(`Unknown action: ${action.type}` )
    }

}

export const CartProvider = ({children}) => {
    const [state, dispatch] = useReducer(reducer, initialState)
    const setCart = (payload) => dispatch({type: SET_CART, payload})

    useEffect(() => {
        getCart()
    },[state]) // Getting the page to be rendered whenever the cart objects are changed

    const getCart = async() => {
        try {
            const cart = await commerce.cart.retrieve()
            
            setCart(cart)

            } catch (error){

         console.log("error")
        }
    }

return (
    <CartDispatchContext.Provider value = {{setCart}}>
      <CartStateContext.Provider value = {state}>
          {children}
      </CartStateContext.Provider>
     </CartDispatchContext.Provider>
)
}

export const useCartState = () => useContext (CartStateContext)
export const useCartDispatch = () => useContext (CartDispatchContext)

CodePudding user response:

The problem here is that you have a useEffect with state as a dependency, meaning that every time the state value is altered, the getCart function gets called.
Meanwhile, getCart sets the state within it.

Therefor, it creates a cycle where getCart sets the state, the useEffect callback runs as a result, getCart gets called again, sets the state again, and so on.

The bottom line is that you can not set the state inside of a function and call that function every time the state value is altered.

  • Related