@@ -134,6 +134,16 @@ export function useSprings(
134134 const ctrls = useRef ( [ ...state . ctrls ] )
135135 const updates = useRef < any [ ] > ( [ ] )
136136
137+ // Backup of the most recently applied updates. The layout effect drains
138+ // `updates.current` after applying so a parent re-render with unchanged
139+ // deps doesn't re-apply stale entries (see #2376). StrictMode mounts
140+ // twice (mount → simulated unmount via `useOnce` cleanup → mount), and the
141+ // second mount needs to restart the controllers after they've been stopped,
142+ // so we keep this snapshot to fall back to. Reset each render so a snapshot
143+ // from a previous commit can never bleed into a subsequent layout effect.
144+ const strictModeRestartSnapshot = useRef < any [ ] > ( [ ] )
145+ strictModeRestartSnapshot . current = [ ]
146+
137147 // Cache old controllers to dispose in the commit phase.
138148 const prevLength = usePrev ( length ) || 0
139149
@@ -201,6 +211,14 @@ export function useSprings(
201211 each ( queue , cb => cb ( ) )
202212 }
203213
214+ // Fall back to the restart snapshot when the primary array has been
215+ // consumed — this lets StrictMode's second mount re-apply updates after
216+ // the simulated cleanup stops the controllers.
217+ const activeUpdates =
218+ updates . current . length > 0
219+ ? updates . current
220+ : strictModeRestartSnapshot . current
221+
204222 // Update existing controllers.
205223 each ( ctrls . current , ( ctrl , i ) => {
206224 // Attach the controller to the local ref.
@@ -212,7 +230,7 @@ export function useSprings(
212230 }
213231
214232 // Apply updates created during render.
215- const update = updates . current [ i ]
233+ const update = activeUpdates [ i ]
216234 if ( update ) {
217235 // Update the injected ref if needed.
218236 replaceRef ( ctrl , update . ref )
@@ -234,6 +252,13 @@ export function useSprings(
234252 }
235253 }
236254 } )
255+
256+ // Snapshot updates before clearing so StrictMode's second mount can
257+ // still access them (see activeUpdates above).
258+ if ( updates . current . length > 0 ) {
259+ strictModeRestartSnapshot . current = updates . current
260+ }
261+ updates . current = [ ]
237262 } )
238263
239264 // Cancel the animations of all controllers on unmount.
0 commit comments