Search code examples
javascriptreactjsreact-button

Open menu with two different buttons


I have a very simple dropdown menu. By clicking on the icon NewIcon in DropdownMenu.Trigger, the user sees a drop-down menu. Everything is simple here. To implement the dropdown menu, I use the radix library (https://www.radix-ui.com/primitives/docs/components/dropdown-menu)

 <DropdownMenu.Root open={isOpen} onOpenChange={setIsOpen}>
  <DropdownMenu.Trigger>
      <NewIcon/>
  </DropdownMenu.Trigger>

  <DropdownMenu.Portal forceMount>
          <DropdownMenu.Content>
         ........here some components
          </DropdownMenu.Content>
  </DropdownMenu.Portal>
</DropdownMenu.Root>

However, I would like to also call this dropdown menu with another button (which is located in another component) on the same page. For example, below is another component that renders the "Edit information" button. Tell me how to click on this button to open the dropdown menu

  <div>           
    <Button>
       Edit information
    </Button>
  <div>

Solution

  • It seems that all you need to do is create a dispatcher that will switch the state to trigger a re-render of the page.

    const MyDropdownMenu = ({ isOpen, onToggle }) => (
      <DropdownMenu.Root open={isOpen} onOpenChange={onToggle}>
        <DropdownMenu.Trigger>
          <NewIcon />
        </DropdownMenu.Trigger>
    
        <DropdownMenu.Portal forceMount>
          <DropdownMenu.Content>
            {/*content */}
          </DropdownMenu.Content>
        </DropdownMenu.Portal>
      </DropdownMenu.Root>
    );
    
    const AnotherComponent = ({ onToggle }) => (
      <div>
        <Button onClick={onToggle}>
          Edit information
        </Button>
    
        <MyDropdownMenu isOpen={false} onToggle={onToggle} />
      </div>
    );
    
    const App = () => {
      const [isOpen, setIsOpen] = useState(false);
    
      const toggleDropdown = () => {
        setIsOpen((prevIsOpen) => !prevIsOpen);
      };
    
      return <AnotherComponent onToggle={toggleDropdown} />;
    };
    
    export default App;

    You can use that with any state manager you prefer. The only thing that will change is the location where the data is stored.

    Extended an example a bit according your comment.

        const MyDropdownMenu = ({ isOpen, onToggle }) => (
    
          const handler = () => {
            console.log(`MyDropdownMenu`);
            onToggle();
          }
          <DropdownMenu.Root open={isOpen} onOpenChange={handler}>
            <DropdownMenu.Trigger>
              <NewIcon />
            </DropdownMenu.Trigger>
    
            <DropdownMenu.Portal forceMount>
              <DropdownMenu.Content>
                {/*content */}
              </DropdownMenu.Content>
            </DropdownMenu.Portal>
          </DropdownMenu.Root>
        );
    
        const AnotherComponent = ({ onToggle }) => (
          const handler = () => {
            console.log(`MyDropdownMenu`);
            onToggle();
          }
          <div>
            <Button onClick={handler}>
              Edit information
            </Button>
    
            <MyDropdownMenu isOpen={false} onToggle={onToggle} />
          </div>
        );
    
        const App = () => {
          const [isOpen, setIsOpen] = useState(false);
    
          const toggleDropdown = () => {
            setIsOpen((prevIsOpen) => !prevIsOpen);
          };
    
          return <AnotherComponent onToggle={toggleDropdown} />;
        };
    
        export default App;