Skip to content

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

@terrymun

Description

@terrymun

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions