bvaughn / react-resizable-panels

https://react-resizable-panels.vercel.app/
MIT License
3.58k stars 124 forks source link

Resize behaviour breaks if PanelResizeHandle rerenders during resizing #342

Closed Fabioni closed 2 months ago

Fabioni commented 2 months ago

Please check that sandbox. The problem is in the comments:

https://codesandbox.io/p/sandbox/react-resizable-panels-forked-tz8mc5

It is one of the typical React nightmares. Having the following in the code rerenders PanelResizeHandle every time the parent rerenders because the prop referentially changes.

<PanelResizeHandle
    hitAreaMargins={{ coarse: x, fine: y }} // this triggers rerender of PanelResizeHandle
/>

Together with setIsCollapsed(true) which triggers a rerender of the parent, this breakes the mouse logic of panel resize. Collapse and Expand in the sandbox and you will know what I mean.

const [isCollapsed, setIsCollapsed] = useState(false);

  return (
    <PanelGroup direction="horizontal">
      <Panel
        onCollapse={() => setIsCollapsed(true)}
      </Panel>
    </PanelGroup>
)

All together:

export default function App() {
  const [isCollapsed, setIsCollapsed] = useState(false);

  return (
    <PanelGroup direction="horizontal">
      <Panel
        minSize={30}
        collapsible
        collapsedSize={10}
        onCollapse={() => setIsCollapsed(true)} // this triggers rerender of App
        onExpand={() => setIsCollapsed(false)} // this triggers rerender of App
        style={{ backgroundColor: "red" }}
      ></Panel>
      <PanelResizeHandle
        style={{ flex: "0 0 20px" }} // this triggers rerender of PanelResizeHandle
        hitAreaMargins={{ coarse: 15, fine: 5 }} // this triggers rerender of PanelResizeHandle
      />

      <Panel minSize={30} style={{ backgroundColor: "orange" }}></Panel>
    </PanelGroup>
  );
}

// using this would prevent from rerendering PanelResizeHandle
const savepropsstyle = { flex: "0 0 20px" };
const savepropsare = { coarse: 15, fine: 5 };
bvaughn commented 2 months ago

FWIW, the inline style prop is not related to the issue you're reporting. Only the inline hitAreaMargins is because the PanelResizeHandle re-initializes itself whenever that object changes. I can refine that logic a bit to extract the fine and coarse values, so that it only re-initializes itself when those change though.

bvaughn commented 2 months ago

Fixed in ae82c4f and released in version 2.0.18. I tested your sandbox to verify that the fix works also.


❤️ → ☕ givebrian.coffee