skip to Main Content

I created a route in my Next.JS app on Firebase and though I intended to be very careful, I get a problem.

First of all here is the code (page.tsx) for the route:

'use client';

import React, {useState,useEffect} from "react";
import firebase from "../../firebase/initFirebase";
import DrillManage from '../components/drillMng'

export default async function MemberPage() {
  const [memberID, setMemberID] = useState("");
  const [userID, setUserID] = useState("");

    if (typeof window !== "undefined") {
        const memberID = window.location.pathname.substring(1)
        setMemberID(memberID)
    } else console.log('window.location is UNDEFINED')

    useEffect(() => {
        let dbRef = firebase.database().ref('Members')
        dbRef.child(memberID)
        .once('value', (snapshot) => {
            const usrID = JSON.parse(JSON.stringify(snapshot.child('UserID')))
            setUserID(usrID)
        })
    }, [memberID]);

    return (
        <DrillManage usrID={userID} />
    )
}

And this is what I see in my web browser:

Unhandled Runtime Error

Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
Call Stack

I don’t see in my code anything which could give raise to some infinite loop.

But I may be wrong. Can anyone spot something I am doing the wrong way? And let me know?

2

Answers


  1. Explanation:
    The value of the following condition remains true

    typeof window !== "undefined"
    

    Which is why the following block of code which is inside the if is getting executed

    const memberID = window.location.pathname.substring(1)
    setMemberID(memberID)
    

    setMemberID changes the state memberID and the component re-renders, and the if block is executed again in the next render and changes the state again, and the component has to re-render every time the state changes. Which is why it is creating an infinite loop.

    Solution:
    Change the following code

    if (typeof window !== "undefined") {
        const memberID = window.location.pathname.substring(1)
        setMemberID(memberID)
    } else console.log('window.location is UNDEFINED')
    

    to the below code

    useEffect(() => {
        if (typeof window !== "undefined") {
            const memberID = window.location.pathname.substring(1)
            setMemberID(memberID)
        } else console.log('window.location is UNDEFINED')
    }, [window]);
    

    Edit:
    If you are using react-router-dom in your project, then you can use

    import { useLocation } from 'react-router-dom';
    

    and inside the component you can change the code to this

    const location = useLocation();
    useEffect(() => {
        if (typeof location !== "undefined") {
            const memberID = location.pathname.substring(1)
            setMemberID(memberID)
        } else console.log('location is UNDEFINED')
    }, [location]);
    
    Login or Signup to reply.
  2. You’re calling a state setter (setMemberId()) during render. That’s big React no-no; it will trigger a re-render and enter an infinite loop.

    Since you’re using Next.js, you should rename your page to [memberId].js and extract the value from the router

    const { query: { memberId } } = useRouter();
    const [userID, setUserID] = useState("");
    
    useEffect(() => {
      let dbRef = firebase.database().ref("Members");
      dbRef.child(memberID).once("value", (snapshot) => {
        // not sure why you'd need JSON.parse/JSON.stringify
        setUserID(snapshot.child("UserID"));
      });
    }, [memberId]);
    

    See https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes

    For information on deploying a Next.js app to Firebase Hosting, see https://firebase.google.com/docs/hosting/frameworks/nextjs


    If you’re having issues with dynamic routes, you can still extract the pathname from the router object

    const { pathname } = useRouter();
    

    You can then use your original logic (or something similar) to extract the memberId.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search