react-rnd icon indicating copy to clipboard operation
react-rnd copied to clipboard

Bug: Conditionally update positions `onResizeStop` causes strange jiggle

Open donrsh opened this issue 2 years ago • 4 comments

Overview of the problem

I'm using react-rnd 10.4.1 [x.x.x]

My browser is: Chrome 108.0.5359.125 on Windows

I am sure this issue is not a duplicate?

Reproduced project

https://codesandbox.io/s/react-rnd-conditionally-resize-jiggle-cvkm8d?file=/src/App.tsx

Description

I want to implement a rnd block in controlled mode, with the constraint that if the block violates some rules (in the above case, the rule is cross the black line) when resizing, then bypass the operation.

It seems to work after resizing. However, when refocus on the rnd block, a strange jiggle happened. But the states (x/y/width/height) aren't changed.

resize-issue

Steps to Reproduce

  1. Resize the rnd block (the red block) from the right-top anchor to cross the black line.
  2. Refocus the rnd block and observe it moves without state changes.

Expected behavior

The rnd block stays where it was before resizing

Actual behavior

The rnd block moves.

donrsh avatar Jan 04 '23 08:01 donrsh

I came up with a workaround. The idea is setting a key on the Rnd element, and update the key if the onResizeStop doesn't commit the resize, to clean up the broken Rnd element. The codes would be like:

function MyRnd() {
const [state, setState] = useState({x, y, width, height })
const [key, updateKey] = useReducer(x => x + 1, 0)

const onResizeStop = useCallback(() => {
  if (!shouldCommitResize()) {
    updateKey();
    return;
  }
  setState(newState);
});

return (
  <Rnd
    key={key}
    position={{...}}
    size={{...}}
    onResizeStop={onResizeStop}
   />
);
}

I've implemented this on the issue codesandbox

donrsh avatar Jan 05 '23 02:01 donrsh

The issue is that x from argument position in function onResizeStop has wrong value. During onResize event, there is wrongly updated position. If we resize an element by one unit, it is okay, but if it is resized by more than one unit, then the position has an offset of 25 more than it should.

In my case, it can be solved by removing this line as it seems that an update is not needed at that point anyway. https://github.com/bokuweb/react-rnd/blob/23d312c5054bf06fd991301fd5604881fa971d46/src/index.tsx#L515

Did not check whole state flow or codebase, so I am not sure from which part that wrong value comes from, but it is definitely a wrong value, and it would be better to fix it there instead of removing the line above.

Rados51 avatar Jun 20 '24 22:06 Rados51

@bokuweb It might be easier for you to spot where exactly the issue comes from, but if you are tight on time, I could possibly do a pull request.

Rados51 avatar Jun 20 '24 22:06 Rados51

@Rados51 Thanks. If it's okay, may I request a pull request?

bokuweb avatar Jun 21 '24 00:06 bokuweb