motiondivision / motiondivision/motion

[BUG] Using a layout effect to imperatively set the position of a draggable element causes it to jump

Open
#1,530 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
TypeScript
Stars
33.7k
Forks
1.4k
Avg merge
1d 10h
Merged PRs (30d)
14

Description

1. Describe the bug

I have a draggable element I'm trying to set the initial position of using a motion value x and style={{ x }}. When I do this via useLayoutEffect, I'm seeing some jumpiness.

3. IMPORTANT: Provide a CodeSandbox reproduction of the bug

Full screen: https://qjrden.csb.app
Code Sandbox: https://codesandbox.io/s/qjrden

4. Steps to reproduce

Steps to reproduce the behavior:

  1. Go to https://qjrden.csb.app (fullscreen version of the app)
  2. Wait for initial render
  3. Resize the window
  4. See the scrubber jump

5. Expected behavior

The scrubber should stay in the same place.

It only happens sometimes. If you can't reproduce, try closing tab, opening a new one and trying again.

If you change useLayoutEffect to useEffect, the bug seems to go away.

6. Video or screenshots

https://user-images.githubusercontent.com/2922250/166490664-f33ca70f-d139-428e-a546-2b5142ae6d8c.mov

Other info

The effect is to set the initial transformX property of the scrubber, and also to update its X position if the prop changes. I'm doing this with a scrubberX MotionValue and passing that into style={{ x: scrubberX }}. Let me know if there's a better way to imperatively set the position of a draggable element. I searched issues and Discord but couldn't put my finger on anything.

I know dragControls lets you call .start(event) on an event, but if I (say) just wanted to set the progress to 25%, I don't have an event, so thought it would be abusing that API to use it. But maybe I can just pass a mock/ducktyped Event into controls.start()?

Contributor guide

Open the contributing guide

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

Reproduce the jump from the linked CodeSandbox by resizing the window after the initial render. Start by comparing the useLayoutEffect and useEffect paths, then inspect the draggable element's MotionValue x/style handling and dragControls behavior. Done means the scrubber retains its position during resize without requiring a mock event.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.