Skip to content

[bug]: Spring reference seem to be shared between instances of the same component when using imperative API #2377

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
1 of 5 tasks
terrymun opened this issue May 24, 2025 · 0 comments
Labels
template: bug This issue might be a bug

Comments

@terrymun
Copy link

terrymun commented May 24, 2025

Which react-spring target are you using?

  • @react-spring/web
  • @react-spring/three
  • @react-spring/native
  • @react-spring/konva
  • @react-spring/zdog

What version of react-spring are you using?

10.0.1

What's Wrong?

The spring reference seems to be shared between renders, when using a callback with useSpring() (needed for access to imperative API). This bug is only reproducible after upgrading from 10.0.0 → 10.0.1, and the only possible explanation is due to this one-liner change here: v10.0.0...v10.0.1#diff-e1288b0efcce202f0575295aec86c6f33c5d81adac9751131dc5d2b08e40e73a

The only logical change between tehse two versions is that the updates.current ??= [] line was removed, which I suspect have triggered this behavior.

To Reproduce

Use the following contrived example: the <Toggle> component will tween a value randomly assigned to it using react-spring, but when clicking between different toggles, the previously clicked button value will also be mutated as the spring is erroneously run:

https://codesandbox.io/p/sandbox/7cz48k (uses 10.0.1, broken)

import { ComponentPropsWithRef, useEffect } from "react";
import { animated, useSpring, to } from "@react-spring/web";

type Props = Omit<ComponentPropsWithRef<"button">, "value"> & {
  value: number;
};

export const Button = ({ value, ...props }: Props) => {
  // NOTE: This is a VERY contrived example, as with the simplified code it is easier not to use a callback
  const [springs, api] = useSpring(() => ({
    ratio: 0,
  }));

  useEffect(() => {
    api.stop().start({
      ratio: value,
    });
  }, [api, value]);

  return (
    <animated.button type="button" {...props} value={springs.ratio}>
      {to([springs.ratio], (r) => r.toFixed(3))}
    </animated.button>
  );
};
Screen.Recording.2025-05-24.at.19.54.57.mov

The same code does not have this incorrect behavior when downgrading back to 10.0.0:

https://codesandbox.io/p/sandbox/2vclkz (uses 10.0.0, works)

Screen.Recording.2025-05-24.at.19.54.40.mov

Expected Behaviour

The spring instance should not be shared between difference instances of the same component.

Link to repo

@terrymun terrymun added the template: bug This issue might be a bug label May 24, 2025
@terrymun terrymun changed the title [bug]: Spring reference seem to be shared between instances of the same component [bug]: Spring reference seem to be shared between instances of the same component when using imperative API May 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
template: bug This issue might be a bug
Projects
None yet
Development

No branches or pull requests

1 participant