next.js & auth0-nextjs node_modules/react-dom/cjs/react-dom-test-utils.development.js @ eval TypeError: Cannot read properties of null (reading ‘0’)

  Kiến thức lập trình

I am trying to implement authentication and user flow on my Nextjs website using auth0, but I am running into an issue with an error that I don’t understand. I am new to Nextjs so this project is somewhat of a learning project for me.

Tech stack used:

  • Nextjs
  • sst to host on was
  • Auth0

Profile page form:

// src/app/profile/page.tsx
"use client";
import React, { useEffect, useState } from "react";
import { useUser, UserProfile } from "@auth0/nextjs-auth0/client";
import Image from "next/image";
import { CameraIcon } from "@heroicons/react/24/outline";
import axios, { AxiosError } from "axios";

type Props = {};

export default function Page({}: Props) {
    const { user, isLoading } = useUser();
    const [userInfo, setUserInfo] = useState<
        | (UserProfile & {
                username?: string;
                family_name?: string;
                phone_number?: string;
          })
        | undefined
    >(undefined);
    const [btnLoading, setBtnLoading] = useState(false);

    const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        setUserInfo({ ...userInfo, name: e.target.value });
    };

    const handleFamilyNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        setUserInfo({ ...userInfo, family_name: e.target.value });
    };

    const handleUsernameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        setUserInfo({ ...userInfo, username: e.target.value });
    };

    const handlePhoneNumberChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        const phoneNumber = e.target.value;

        if (phoneNumber.length > 1 && !phoneNumber.startsWith("+46")) {
            setUserInfo({ ...userInfo, phone_number: `+46${phoneNumber}` });
        } else {
            setUserInfo({ ...userInfo, phone_number: phoneNumber });
        }
    };

    const handleSave = async () => {
        if (!userInfo) return;
        const { sub, name, family_name, nickname } = userInfo;

        setBtnLoading(true);
        const response = await axios
            .patch(`/api/profile?sub=${sub}`, {
                name,
                family_name,
                nickname
            })
            .catch((error: AxiosError) => {
                console.error("???? ~ handleSave ~ error:", error.response?.data);
            });
        console.log("???? ~ handleSave ~ response:", response);

        setBtnLoading(false);
    };

    useEffect(() => {
        setUserInfo(user);
    }, [user]);

    return (
        <div className='flex flex-col justify-center items-center gap-5 px-2 md:px-0'>
            {isLoading ? (
                <div className='flex justify-center item-center w-screen h-screen'>
                    <span className='loading loading-infinity loading-lg text-secondary'></span>
                </div>
            ) : (
                <>
                    <h1 className='text-3xl font-bold'>Profil</h1>
                    <div className='avatar'>
                        <div className='w-40 mask mask-hexagon flex justify-center item-center bg-slate-950 group cursor-pointer'>
                            <Image
                                src={userInfo?.picture || ""}
                                width={64}
                                height={64}
                                alt='Profile picture'
                                className='group-hover:opacity-75 group-active:opacity-50 transition-opacity'
                            />
                            <div className='relative z-50'>
                                <CameraIcon className='opacity-0 w-6 h-6 group-hover:opacity-100 transition-opacity' />
                            </div>
                        </div>
                    </div>

                    <label className='form-control w-full max-w-xs'>
                        <div className='label'>
                            <span className='label-text'>Mail</span>
                        </div>
                        <input
                            type='text'
                            placeholder='Type here'
                            className='input input-bordered w-full max-w-xs'
                            disabled
                            value={userInfo?.email || ""}
                        />
                    </label>

                    <label className='form-control w-full max-w-xs'>
                        <div className='label'>
                            <span className='label-text'>Förnamn</span>
                        </div>
                        <input
                            type='text'
                            placeholder='Type here'
                            className='input input-bordered w-full max-w-xs'
                            onChange={handleNameChange}
                            value={userInfo?.name || ""}
                        />
                    </label>

                    <label className='form-control w-full max-w-xs'>
                        <div className='label'>
                            <span className='label-text'>Efternamn</span>
                        </div>
                        <input
                            type='text'
                            placeholder='Type here'
                            className='input input-bordered w-full max-w-xs'
                            onChange={handleFamilyNameChange}
                            value={userInfo?.family_name || ""}
                        />
                    </label>

                    <label className='form-control w-full max-w-xs'>
                        <div className='label'>
                            <span className='label-text'>Användernamn</span>
                        </div>
                        <input
                            type='text'
                            placeholder='Type here'
                            className='input input-bordered w-full max-w-xs'
                            onChange={handleUsernameChange}
                            value={userInfo?.username || ""}
                        />
                    </label>

                    <label className='form-control w-full max-w-xs'>
                        <div className='label'>
                            <span className='label-text'>Mobil nummer</span>
                        </div>
                        <input
                            type='text'
                            placeholder='07XXXXXXXX'
                            className='input input-bordered w-full max-w-xs'
                            onChange={handlePhoneNumberChange}
                            value={userInfo?.phone_number || ""}
                        />
                    </label>

                    <button
                        onClick={() => handleSave()}
                        className='btn btn-primary btn-xl w-full max-w-xs'
                    >
                        {btnLoading ? (
                            <span className='loading loading-infinity loading-lg'></span>
                        ) : (
                            "Spara"
                        )}
                    </button>
                </>
            )}
        </div>
    );
}

profile route:

// src/app/api/profile/route.ts
import { Auth0Service } from "@/services/auth0-service";
import { streamRead as streamReader } from "@/utils/streamRead";
import { getQueryStringParamFromURL } from "@/utils";

export const PATCH = async (req: Request) => {
    if (!req.body) {
        return new Response("Missing body", { status: 400 });
    }

    const sub = getQueryStringParamFromURL("sub", req.url);

    if (!sub) {
        return new Response("User id missing", { status: 400 });
    }

    const user = await streamReader(req.body);

    const userWithId = { ...user, sub: sub };
    const updatedUser = await Auth0Service.handleUpdateUserInfo(userWithId);

    return new Response(JSON.stringify({ updatedUser }), { status: 200 });
};

the auth0 service that should take care of sending the PATCH request to auth0:

// src/services/auth0-service.ts
import { auth0 } from "@/utils";
import { Auth0Config } from "@/utils/auth0/auth0-config";
import axios, { AxiosError } from "axios";

class Auth0ServiceImpl {
    async handleUpdateUserInfo(user: any) {
        const { sub, name, family_name, nickname } = user;
        const response = await axios
            .patch(
                `https://[id].us.auth0.com/api/v2/users/${sub}`,
                {
                    name,
                    family_name,
                    nickname
                },
                {
                    headers: {
                        Authorization: `Bearer ${Auth0Config.AUTH0_MANAGEMENT_API_TOKEN}`
                    }
                }
            )
            .catch((error: AxiosError) => {
                console.error("???? ~ handleSave ~ error:", error.response?.data);
            });

        return response;
    }
}

export const Auth0Service = new Auth0ServiceImpl();

The error that I am getting:

 ⨯ node_modules/react-dom/cjs/react-dom-test-utils.development.js (1127:0) @ eval
 ⨯ TypeError: Cannot read properties of null (reading '0')
    at eval (webpack-internal:///(rsc)/./node_modules/react-dom/cjs/react-dom-test-utils.development.js:1127:41)
    at eval (webpack-internal:///(rsc)/./node_modules/react-dom/cjs/react-dom-test-utils.development.js:1740:5)
    at (rsc)/./node_modules/react-dom/cjs/react-dom-test-utils.development.js (/Users/someuser/Documents/git/project/frontend/.next/server/vendor-chunks/react-dom.js:20:1)
    at __webpack_require__ (/Users/someuser/Documents/git/project/frontend/.next/server/webpack-runtime.js:33:43)
    at eval (webpack-internal:///(rsc)/./node_modules/react-dom/test-utils.js:4:20)
    at (rsc)/./node_modules/react-dom/test-utils.js (/Users/someuser/Documents/git/project/frontend/.next/server/vendor-chunks/react-dom.js:30:1)
    at __webpack_require__ (/Users/someuser/Documents/git/project/frontend/.next/server/webpack-runtime.js:33:43)
    at eval (webpack-internal:///(rsc)/./node_modules/@testing-library/react/dist/@testing-library/react.esm.js:86:78)
    at (rsc)/./node_modules/@testing-library/react/dist/@testing-library/react.esm.js (/Users/someuser/Documents/git/project/frontend/.next/server/vendor-chunks/@testing-library.js:1510:1)
    at __webpack_require__ (/Users/someuser/Documents/git/project/frontend/.next/server/webpack-runtime.js:33:43)
    at eval (webpack-internal:///(rsc)/./src/utils/testing/testing-utils.ts:6:80)
    at (rsc)/./src/utils/testing/testing-utils.ts (/Users/someuser/Documents/git/project/frontend/.next/server/app/api/profile/route.js:388:1)
    at __webpack_require__ (/Users/someuser/Documents/git/project/frontend/.next/server/webpack-runtime.js:33:43)
    at eval (webpack-internal:///(rsc)/./src/utils/testing/index.ts:5:72)
    at (rsc)/./src/utils/testing/index.ts (/Users/someuser/Documents/git/project/frontend/.next/server/app/api/profile/route.js:378:1)
    at __webpack_require__ (/Users/someuser/Documents/git/project/frontend/.next/server/webpack-runtime.js:33:43)
    at eval (webpack-internal:///(rsc)/./src/utils/index.ts:8:66)
    at (rsc)/./src/utils/index.ts (/Users/someuser/Documents/git/project/frontend/.next/server/app/api/profile/route.js:358:1)
    at __webpack_require__ (/Users/someuser/Documents/git/project/frontend/.next/server/webpack-runtime.js:33:43)
    at eval (webpack-internal:///(rsc)/./src/app/api/profile/route.ts:7:64)
    at (rsc)/./src/app/api/profile/route.ts (/Users/someuser/Documents/git/project/frontend/.next/server/app/api/profile/route.js:242:1)
    at __webpack_require__ (/Users/someuser/Documents/git/project/frontend/.next/server/webpack-runtime.js:33:43)
    at eval (webpack-internal:///(rsc)/./node_modules/next/dist/build/webpack/loaders/next-app-loader.js?name=app%2Fapi%2Fprofile%2Froute&page=%2Fapi%2Fprofile%2Froute&appPaths=&pagePath=private-next-app-dir%2Fapi%2Fprofile%2Froute.ts&appDir=%2FUsers%2Fsomeuser%2FDocuments%2Fgit%2Fproject%2Ffrontend%2Fsrc%2Fapp&pageExtensions=tsx&pageExtensions=ts&pageExtensions=jsx&pageExtensions=js&rootDir=%2FUsers%2Fsomeuser%2FDocuments%2Fgit%2Fproject%2Ffrontend&isDev=true&tsconfigPath=tsconfig.json&basePath=&assetPrefix=&nextConfigOutput=standalone&preferredRegion=&middlewareConfig=e30%3D!:17:139)

LEAVE A COMMENT