react-grid-layout / react-grid-layout/react-draggable

Draggable shifts position after reload of page (persistent coordinates)

Open
#616 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
9.3k
Forks
1k
Avg merge
3d 8h
Merged PRs (30d)
4

Description

Hi,
I am developing an application where users can create views consisting of draggable components. As i want the views to be persistent i store the x/y-coordinates of each component in a database. When a page (view) is rendered, i then fetch the coordinates and use these to populate the view (using the defaultPosition-prop)

This works great but i have an infuriating problem. The first time a view is refreshed after a new component is added to a view (and saved), the components will shift position down and to the right. I made a short video showcasing the problem:
https://streamable.com/h00fm8

As can be seen in the console - the coordinates used when rendering the view after the reload are identical to the ones that are saved, but for some reason the element moves!

Here is my draggable component:

return (
      <Draggable
        grid={[25, 25]} disabled={!props.editingEnabled} defaultPosition={{x: x, y: y}}  onStop={handleStop}>
        <div style={{position: "static"}} //have tried with absolute and fixed as well, didn't help
            <h1>Testing</h1>
        </div>
      </Draggable>
    )

handleStop:

  const handleStop = (event) => {
    let x = event.layerX;
    let y = event.layerY;
    console.log("Saving position of element");
    console.log("Saving X/Y-position " + x + ", " + y);
    setX(x);
    setY(y);
    props.handleMoveCallback(x, y, props.componentName)
  };

handleMoveCallback is in the parent of the element:

 handleMoveCallback = (x, y, componentName) => {
    this.updateComponent(x, y, componentName);
  };

updateComponent = (x, y, componentName) => {
    let existingPositions = this.state.componentPositions;
    if (existingCompNames.includes(componentName)) {
      let objIndex = existingPositions.findIndex((ep => ep.componentName === componentName));
      existingPositions[objIndex].x = x;
      existingPositions[objIndex].y = y;
      this.setState(
         { componentPositions: existingPositions }, this.saveView());
    }
  };

saveView just posts the array of component positions to the backing API where it's stored in the database.
The components are then rendered inside of an absolute position div:

....
let components = this.state.componentPositions.map((c) =>
     <DraggableFunctionComponent id={c.componentName}  key={c.componentName}
                                 x={c.x} y={c.y}
                                  componentName={c.componentName} parentCallBack={this.handleMoveCallback}                      
     />
.....
<div style={{ position: "absolute" }}>   
             {components}   
</div>

Any help would be greatly appreciated

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the reload behavior around the Draggable component using defaultPosition, then trace the coordinates through handleStop, updateComponent, saveView, and the parent render. Compare the persisted values with the position applied after reload; done means components retain their saved coordinates after refreshing the page.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, react
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.