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

Unable to trigger 'open' state on DropdownMenu when controlled #2564

Closed
changgun-park opened this issue Dec 5, 2023 · 1 comment
Closed

Comments

@changgun-park
Copy link

Bug report

Current Behavior

The dropdown will open as expected when its open state is not controlled.
However, when the state is controlled,

I have made implementation and test for each case.

// uncontrolled
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";

export function UncontrolledDropdown() {
  return (
    <DropdownMenu.Root>
      <DropdownMenu.Trigger>Trigger</DropdownMenu.Trigger>
      <DropdownMenu.Portal>
        <DropdownMenu.Content>
          <DropdownMenu.Item>Item 1</DropdownMenu.Item>
          <DropdownMenu.Item>Item 2</DropdownMenu.Item>
          <DropdownMenu.Item>Item 3</DropdownMenu.Item>
        </DropdownMenu.Content>
      </DropdownMenu.Portal>
    </DropdownMenu.Root>
  );
}

And the following test passes.

import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { UncontrolledDropdown } from "./uncontrolled-dropdown";

it("renders without crashing", async () => {
  const user = userEvent.setup();

  render(<UncontrolledDropdown />);

  await user.click(screen.getByText("Trigger"));
  expect(screen.getByRole("menu")).toBeInTheDocument();
});

Here is the controlled version

import { useState } from "react";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";

/**
 *
 */
export function ControlledDropdown() {
  const [open, setOpen] = useState(false);

  return (
    <DropdownMenu.Root open={open}>
      <DropdownMenu.Trigger onClick={() => setOpen(true)}>
        Trigger
      </DropdownMenu.Trigger>
      <DropdownMenu.Portal>
        <DropdownMenu.Content>
          <DropdownMenu.Item>Item 1</DropdownMenu.Item>
          <DropdownMenu.Item>Item 2</DropdownMenu.Item>
          <DropdownMenu.Item>Item 3</DropdownMenu.Item>
        </DropdownMenu.Content>
      </DropdownMenu.Portal>
    </DropdownMenu.Root>
  );
}

And the following test will fail. It will fail to query for an element with role 'menu'.

import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { UncontrolledDropdown } from "./uncontrolled-dropdown";

it("renders without crashing", async () => {
  const user = userEvent.setup();

  render(<UncontrolledDropdown />);

  await user.click(screen.getByText("Trigger"));
  expect(screen.getByRole("menu")).toBeInTheDocument();
});

Expected behavior

Whether the component is controlled or not should not impact the test.

Reproducible example

CodeSandbox

Suggested solution

Not really sure what's going on here.

Additional context

I have tried to mock PointerEvent as Suggested by #856, but it doesn't fix the issue.

Your environment

Software Name(s) Version
Radix Package(s) react-dropdown-menu 2.0.6
React n/a 18.2.0
Browser chrome
Node n/a 18.18
npm/yarn 1.22.19(yarn)
Operating System MacOS
@changgun-park
Copy link
Author

I'm sorry, simply passing a handler to onOpenChange fixes this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant