Is there an existing issue for this?
Describe the issue
The image-loading effect in Image lists onError, onLoad, onLoadEnd, and onLoadStart in its dependency array (source). Passing inline handlers — new function identities on every parent render — re-runs the effect for an unchanged uri: the cleanup aborts the in-flight request, state resets to LOADING, onLoadStart fires again, and the load restarts. If a handler sets state (e.g. onLoadEnd={() => setLoading(false)}), the re-render produces fresh identities and the cycle loops indefinitely — the image never settles even though the browser has it fully decoded. React Native is unaffected by handler identity, so code that works on iOS/Android breaks on web.
Test case: https://codesandbox.io/p/sandbox/rnw-image-callback-identity-repro-forked-y6mngh — watch the onLoadStart/onLoadEnd call counters climb indefinitely while "Loading..." never settles, and the network panel restart the same request.
Hit in production in rn-story: the story viewer's loader flickered forever on web while working fine on iOS/Android. Worked around in v2.0.1 by memoizing every handler with useCallback.
Related history: the source-object version of this problem was addressed by having the effect depend on the resolved uri string rather than the object — the callbacks still retrigger it. I have a fix with regression tests ready and will open a PR.
Expected behavior
One load per uri. onLoadStart, onLoad, and onLoadEnd fire once per actual load, regardless of how often the parent re-renders or whether the handlers are inline functions. Changing a handler's identity should never abort an in-flight request, reset state to LOADING, or re-fire onLoadStart — when the load settles, the most recent handlers should be invoked. This matches React Native, where handler identity has no effect on loading.
Steps to reproduce
- Render an
<Image source={{ uri }}> with inline onLoadStart={() => setLoading(true)} and onLoadEnd={() => setLoading(false)}.
- The load completing sets state → re-render → new handler identities → the load effect re-runs, aborts, and restarts the load for the same uri.
- Observe the loop in https://codesandbox.io/p/sandbox/rnw-image-callback-identity-repro-forked-y6mngh (call counters + network panel).
Test case
https://codesandbox.io/p/sandbox/rnw-image-callback-identity-repro-forked-y6mngh
Additional comments
No response
Is there an existing issue for this?
Describe the issue
The image-loading effect in Image lists onError, onLoad, onLoadEnd, and onLoadStart in its dependency array (source). Passing inline handlers — new function identities on every parent render — re-runs the effect for an unchanged uri: the cleanup aborts the in-flight request, state resets to LOADING, onLoadStart fires again, and the load restarts. If a handler sets state (e.g. onLoadEnd={() => setLoading(false)}), the re-render produces fresh identities and the cycle loops indefinitely — the image never settles even though the browser has it fully decoded. React Native is unaffected by handler identity, so code that works on iOS/Android breaks on web.
Test case: https://codesandbox.io/p/sandbox/rnw-image-callback-identity-repro-forked-y6mngh — watch the
onLoadStart/onLoadEndcall counters climb indefinitely while "Loading..." never settles, and the network panel restart the same request.Hit in production in rn-story: the story viewer's loader flickered forever on web while working fine on iOS/Android. Worked around in v2.0.1 by memoizing every handler with
useCallback.Related history: the
source-object version of this problem was addressed by having the effect depend on the resolved uri string rather than the object — the callbacks still retrigger it. I have a fix with regression tests ready and will open a PR.Expected behavior
One load per uri.
onLoadStart,onLoad, andonLoadEndfire once per actual load, regardless of how often the parent re-renders or whether the handlers are inline functions. Changing a handler's identity should never abort an in-flight request, reset state toLOADING, or re-fireonLoadStart— when the load settles, the most recent handlers should be invoked. This matches React Native, where handler identity has no effect on loading.Steps to reproduce
<Image source={{ uri }}>with inlineonLoadStart={() => setLoading(true)}andonLoadEnd={() => setLoading(false)}.Test case
https://codesandbox.io/p/sandbox/rnw-image-callback-identity-repro-forked-y6mngh
Additional comments
No response