React-spring: Update duration in config not working properly

Created on 30 Sep 2020  路  9Comments  路  Source: pmndrs/react-spring

When I update the duration via useState, animation flickers back, not to initial value though.

I think you will understand from codesandbox example. Try to click the button, once the animation is 50% done.

codesandbox example

bug v9

All 9 comments

Thanks for reporting! I'll try to fix it before the next release.

@aleclarson thanks for the reply, do you know if there is some workaround this, I really need this feature for my current project?

Here ya go

  const { x } = useSpring({
    from: {  x: 0  },
  });

  React.useEffect(() => {
    x.start(500, {
      config: { duration: customDuration }  
    })
  }, [x, customDuration])

PS: You can become my patron to support my work.

@aleclarson this doesn't seem to be working 馃
And I'm not sure I understand what's happening here :D Do I not need to specify to: { x: 500} anymore?
Does this x.start(500... mean that after I click the button, there won't be any flickers?

Update: I'm getting this error Cannot call "start" of disposed "SpringValue" object

That error appears because of hot reloading. It's been fixed for the next release.

Your sandbox (with the workaround) is working for me, no jumping. 馃槄

It's using the SpringValue API, which lets you pass the to prop as the first argument, but you could pass { to: 500, config } instead if you find that more readable.

@aleclarson you are a lifesaver, thank you! Everything is working now.

@aleclarson I found out that the new duration is set for different ranges.

Example:
initial 0, goal 100 - duration 5s

on button click
initial (let's say) 40, goal 100 - duration 5s

The second one will be faster than you would think because the range is 60 (100 - 40).

From my point of view, the speed shouldn't change 馃

I could calculate the proper duration value thought by applying proportions, but the main issue here is for loop, when the loop starts again, duration is already different.

Can you open another issue for that question? Thanks 馃榿

@aleclarson I've just found out a hacky solution I guess xD

  const { translate } = useSpring({
    from: { translate: 0 },
  })

  useEffect(() => {
    /** We need this useEffect for seamless transitions when changing speed */
    const startAnimation = async (): Promise<void> => {
      await translate.start(1, {
        config: {
          duration:
            slowOnHover && isHovering
              ? (1 - translate.get()) * duration * 7
              : (1 - translate.get()) * duration,
        },
        loop: {
          reset: true,
          config: { duration },
        },
      })
    }
    console.log('effect', translate.get())

    // eslint-disable-next-line @typescript-eslint/no-floating-promises
    startAnimation()
  })

I didn't know that we can pass config into the loop property.

And this one helps to calculate proper duration: js 1 - translate.get()

Was this page helpful?
0 / 5 - 0 ratings