DEV Community

ibkay998
ibkay998

Posted on

Fixing Nasty Bugs(Understanding Modals) - Part 1

Debugging an Annoying Bug in a Next.js Project

Sometime last week, I began working on a new project primarily built with Next.js and styled using the Shadcn component library. While building, I encountered a particularly annoying bug that not only slowed me down but also pushed me to reconsider my approach to debugging and understanding the tools I work with.

Why Write About This?

The purpose of writing this article is to force myself to dive deeper into understanding the inner workings of components and frameworks. In the past, I’ve written code that worked fine but would not have the time to understand deeply what I have written. This time, I want to adopt a systematic approach to force me to learn the inner workings of things and nothing forces you to slow down when coding the hitting a bug. Writing about it will help me reflect, learn, and share my journey.

Systematic Approach to Debugging

To resolve this issue, I’ve broken the debugging process into three systematic steps:

  1. Replicate the Bug: Go back to the specific commit where the issue occurred, review the code, and reliably reproduce the error.
  2. Understand Why the Bug Happens: Analyze the root cause and the interaction between the components that led to the problem.
  3. Fix the Bug: Implement a solution and validate it.

This article will cover the first step in detail.


Replicating the Bug

Here is the problematic component that caused me so much trouble:

Code Snippet: OrganizationDetailsModal

"use client";
import { motion } from "framer-motion";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogClose, DialogFooter } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import Image from "next/image";
import { useState } from "react";

const OrganizationDetailsModal: React.FC<OrganizationDetailsModalProps> = ({ hideModal, organization }) => {
  const [open, setOpen] = useState(true);
  const handleClose = () => {
    hideModal();
    setOpen(false);
  };

  return (
    <Dialog
      open={open}
      onOpenChange={(isOpen) => {
        if (!isOpen) {
          handleClose();
        }
      }}
    >
      <DialogContent
        onCloseAutoFocus={(e) => {
          e.preventDefault();
          const safeElement = document.getElementById("safe-focus-element");
          if (safeElement) safeElement.focus();
        }}
        className="flex max-h-[80vh] w-[400px] flex-col rounded-xl bg-white px-5 py-4 overflow-y-auto"
      >
        <DialogHeader>
          <div className="flex justify-between items-center">
            <DialogTitle>Organisation Details</DialogTitle>
            <DialogClose asChild>
              <button onClick={handleClose} className="text-gray-700 hover:text-gray-900">X</button>
            </DialogClose>
          </div>
        </DialogHeader>

        <div className="space-y-4">
          <div className="flex justify-between">
            <span className="text-sm font-semibold">Organization Name</span>
            <span className="text-sm">{organization.organizationName}</span>
          </div>
        </div>

        <DialogFooter>
          <button onClick={handleClose} className="bg-primary-green text-white px-4 py-2 rounded-md">
            Back
          </button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
};

export default OrganizationDetailsModal;
Enter fullscreen mode Exit fullscreen mode

Code Snippet: Dropdown Menu

<DropdownMenu>
  <DropdownMenuTrigger className="focus:outline-none">
    <MoreHorizontal className="h-5 w-5 cursor-pointer" />
  </DropdownMenuTrigger>
  <DropdownMenuContent align="start" sideOffset={4} className="rounded-md p-1 shadow-md">
    {rowMenuItems.map((menuItem, menuIndex) => (
      <DropdownMenuItem
        key={menuIndex}
        onClick={() => menuItem.onClick(row)}
        className="flex justify-start gap-2 px-3 py-2 hover:bg-gray-100"
      >
        {menuItem.icon && <Image src={menuItem.icon} alt={menuItem.label} />}
        <span>{menuItem.label}</span>
      </DropdownMenuItem>
    ))}
  </DropdownMenuContent>
</DropdownMenu>
Enter fullscreen mode Exit fullscreen mode

What These Components Do

  1. Dropdown Menu: When clicked, this component displays a dropdown list of actions.

Image description

  1. Dialog Component: This modal dialog is triggered by selecting an action from the dropdown. It displays detailed information and has a close button to dismiss it.

Image description

The Bug

When the dropdown is clicked, it opens as expected. Inside the dropdown, there’s an option to view details, which triggers the Dialog component to appear. The problem occurs when the dialog is closed—nothing else on the page is clickable afterward. This was perplexing because both components seemed to work perfectly in isolation.


The Frustration

Despite spending several hours investigating, I couldn’t pinpoint the cause of the issue. The interaction between the dropdown and dialog components appeared to create some kind of state inconsistency or DOM issue.

Eventually, I opted to replace one of the components entirely, which resolved the issue temporarily. However, I was left unsatisfied without understanding the root cause, which is what I plan to explore further.

Conclusion

This concludes the first part of my debugging journey—replicating the bug and documenting the problem. In the next part, I will dive deeper into the inner workings of these components to understand what might have caused this unusual behavior. By doing so, I hope to gain insights that will help me fix similar bugs in the future and grow as a developer.

Stay tuned for Part 2: Understanding Why the Bug Happens.

Top comments (0)