Search code examples
reactjsdrag-and-droprefconditional-renderingreact-forwardref

Conditionally rendering a component inside of <Draggable>, using react-draggable, is breaking the draggable functionality. Any ideas?


I'm trying to conditionally render a component inside another component that uses react-draggable. If my return function returns a div, dragging works fine. If my function returns SomeComponent, dragging breaks completely. I've tried React.forwardRef and attaching the ref to nodeRef on Draggable, and on the ref inside the component, but that doesn't work. Is this maybe a limit of react-draggable?

const Master = () => {
  const nodeRef = useRef(null);

  const renderComponent = (type) => {
    switch (type) {
      case "typography":
        // If we return <Typography />, drag stops working.
        // return <Typography content="Hello!" ref={nodeRef} />; // Not Working
        return <div ref={nodeRef}>hello</div>; // Working
      case "button":
        return <button>Click Me</button>;
      default:
        break;
    }
  };
  return (
    <Draggable nodeRef={nodeRef}>{renderComponent("typography")}</Draggable>
  );
};
const Typography = React.forwardRef(({ content }, ref) => {
  return <div ref={ref}>{content}</div>;
});

Here is a link to a forked codesandbox if you want to check it out. https://codesandbox.io/s/gallant-voice-ly8jyj?file=/src/Master.js:113-673

Thanks everyone!


Solution

  • Wrapping the renderComponent call in a div seems to solve the issue:

    const Master = () => {
      const nodeRef = useRef(null);
    
      const renderComponent = (type) => {
        switch (type) {
          case "typography":
            return <Typography content="Hello!" />;
          case "button":
            return <button>Click Me</button>;
          default:
            break;
        }
      };
      return (
        <Draggable nodeRef={nodeRef}>
          <div ref={nodeRef}>{renderComponent("typography")}</div>
        </Draggable>
      );
    };
    

    You also don't require forwardRef in this case