title: React CTA with Modal in DropDown Pattern
body: <p>I'm using MaterialUI's ButtonGroup as a drop down menu and having a pattern issue trying to create a series of CTAs which I can easily swap around in it; where all of the components are reusable and the choices in the dropdown is dynamic, i.e.</p>
  
  <pre><code>const CTAs = [
    &lt;Foo {...foo} /&gt;, // these look like &lt;MenuItem&gt;{blah}&lt;/MenuItem&gt;
    &lt;Bar {...bar} /&gt;,
    &lt;Baz {...baz} /&gt;,
  ];
  return (
    &lt;DropDown&gt;
      {CTAs}
    &lt;/DropDown&gt;
  );
  </code></pre>
  
  <pre><code> // DropDown looks something like this
    const [open, setOpen] = React.useState&lt;boolean&gt;(false);
    const anchorRef = React.useRef&lt;HTMLDivElement&gt;(null);
  
    return (
      &lt;Grid container direction="column" alignItems="center"&gt;
        &lt;Grid item xs={12}&gt;
          &lt;ButtonGroup variant="contained" ref={anchorRef}&gt;
            &lt;Button
              variant="contained"
              onClick={toggleOpen}
            &gt;
              {label}
            &lt;/Button&gt;
          &lt;/ButtonGroup&gt;
          &lt;ListWrapper
            anchorEl={anchorRef.current}
            open={open}
            setOpen={setOpen}
          &gt; {/* Popper &gt; Grow &gt; Paper &gt; ClickAwayListener &gt; MenuList &gt; children */}
            {children}
          &lt;/ListWrapper&gt;
        &lt;/Grid&gt;
      &lt;/Grid&gt;
    );
  </code></pre>
  
  <p>However, I'm running into issues when some of these CTAs need a modal confirmation as the modals break inside the dropdown; the dropdown captures text entry and closing the dropdown destroys the modal.</p>
  
  <p>How do I do this?</p>
  
  <hr>
  
  <p>What I've tried,</p>
  
  <p>I've worked around this by adding a function that returns two nodes instead of just one;</p>
  
  <pre><code>interface CTAState {
    open: boolean;
    // and other stuff that used to be inside the CTAs
  }
  
  const GetFoo = (props): [React.ReactNode, React.ReactNode] =&gt; {
    const [state, setState] = React.useState&lt;CTAState&gt;({ open: false });
    const setOpen = (val: boolean): void =&gt; setState((prevState) =&gt; ({
      ...prevState,
      open: val,
    }));
  
    const onSend = (): void =&gt; {
      // do cool stuff which used to be in &lt;Foo /&gt; click
      setOpen(false);
    };
  
    return [
      (&lt;Foo {...props} onClick={() =&gt; setOpen(true)} /&gt;),
      (&lt;Dialog open={state.open} onSend={onSend} /&gt;),
    ];
  };
  
  // .. 
  
  const CTAs = [GetFoo(foo), GetBar(bar), GetBaz(baz)];
  
  return (
    &lt;DropDown&gt;
      {CTAs.map(([button]) =&gt; button)}
    &lt;/DropDown&gt;
    {CTAs.map(([, dialog]) =&gt; dialog)}
  );
  </code></pre>
  
  <p>This seems like an anti-pattern as I'm having to use something which is not a Component with a react hook to handle state, the complexity just keeps growing and it is becoming very difficult to track what is going on within the CTA itself</p>
  
  <p>What is the way to do this?</p>