Skip to content

Commit 328f2bc

Browse files
authored
test(core): cover declarative useSpring auto-start under StrictMode (#2361) (#2531)
1 parent 5c5972b commit 328f2bc

1 file changed

Lines changed: 66 additions & 0 deletions

File tree

packages/core/src/hooks/useSpring.test.tsx

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,72 @@ describe('useSpring', () => {
223223
})
224224
})
225225

226+
// Regression tests for https://github.com/pmndrs/react-spring/issues/2361
227+
// (and the earlier https://github.com/pmndrs/react-spring/issues/2146).
228+
// A declarative `useSpring` with no ref should auto-animate on mount even
229+
// under StrictMode, whose double-mount (mount → simulated unmount → mount)
230+
// used to leave the controller stopped with an empty `updates` array.
231+
describe('when a declarative props object is passed with no ref (StrictMode)', () => {
232+
it('animates from→to on mount', async () => {
233+
const onStart = vi.fn()
234+
const onRest = vi.fn()
235+
let spring: SpringValue<number> | undefined
236+
237+
function Component() {
238+
const springs = useSpring({
239+
from: { opacity: 0 },
240+
to: { opacity: 1 },
241+
config: { duration: 100 },
242+
onStart,
243+
onRest,
244+
})
245+
spring = springs.opacity as unknown as SpringValue<number>
246+
return null
247+
}
248+
249+
await render(
250+
<React.StrictMode>
251+
<Component />
252+
</React.StrictMode>
253+
)
254+
await advanceUntilIdle()
255+
256+
expect(spring?.get()).toBe(1)
257+
expect(onStart).toHaveBeenCalledTimes(1)
258+
expect(onRest).toHaveBeenCalledTimes(1)
259+
})
260+
261+
it('keeps a looped animation running on mount', async () => {
262+
const onStart = vi.fn()
263+
let spring: SpringValue<number> | undefined
264+
265+
function Component() {
266+
const springs = useSpring({
267+
from: { x: 0 },
268+
to: { x: 100 },
269+
loop: true,
270+
config: { duration: 100 },
271+
onStart,
272+
})
273+
spring = springs.x as unknown as SpringValue<number>
274+
return null
275+
}
276+
277+
await render(
278+
<React.StrictMode>
279+
<Component />
280+
</React.StrictMode>
281+
)
282+
283+
// A loop never goes idle, so step until it has driven the value forward.
284+
await advanceUntilValue(spring!, 50)
285+
286+
expect(spring!.get()).toBeGreaterThanOrEqual(50)
287+
expect(spring!.isAnimating).toBe(true)
288+
expect(onStart).toHaveBeenCalled()
289+
})
290+
})
291+
226292
// Regression test for https://github.com/pmndrs/react-spring/issues/1638
227293
// The original bug (v9.2.4): a spring with initial value 0 would not
228294
// animate when api.start() was called from useLayoutEffect on first render.

0 commit comments

Comments
 (0)