Skip to content

Commit c47935c

Browse files
kidrocanecolas
authored andcommitted
[fix] Image: image LOADED state is only captured initially
If the Image component is rendered with a `null` source, and consecutively updated with actual source url that was already loaded, it would fail to pick up the change - `state` would be `IDLE` for a brief moment and this would cause a small flicker when the image renders Let's always start from IDLE state, and update `shouldDisplaySource` condition to be based on `ImageLoader.has` cache or not Fix #2492
1 parent 160f50f commit c47935c

File tree

3 files changed

+18
-25
lines changed

3 files changed

+18
-25
lines changed

packages/react-native-web/src/exports/Image/__tests__/__snapshots__/index-test.js.snap

+10-10
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ exports[`components/Image prop "source" is correctly updated when missing in ini
255255
</div>
256256
`;
257257

258-
exports[`components/Image prop "source" is not set immediately if the image has not already been loaded 1`] = `
258+
exports[`components/Image prop "source" is set immediately if the image has already been loaded 1`] = `
259259
<div
260260
class="css-view-175oi2r r-flexBasis-1mlwlqe r-overflow-1udh08x r-zIndex-417010"
261261
>
@@ -272,53 +272,53 @@ exports[`components/Image prop "source" is not set immediately if the image has
272272
</div>
273273
`;
274274

275-
exports[`components/Image prop "source" is set immediately if the image has already been loaded 1`] = `
275+
exports[`components/Image prop "source" is set immediately if the image has already been loaded 2`] = `
276276
<div
277277
class="css-view-175oi2r r-flexBasis-1mlwlqe r-overflow-1udh08x r-zIndex-417010"
278278
>
279279
<div
280280
class="css-view-175oi2r r-backgroundColor-1niwhzg r-backgroundPosition-vvn4in r-backgroundRepeat-u6sd8q r-bottom-1p0dtai r-height-1pi2tsx r-left-1d2f490 r-position-u8s1d r-right-zchlnj r-top-ipm5af r-width-13qz1uu r-zIndex-1wyyakw r-backgroundSize-4gszlv"
281-
style="background-image: url(https://google.com/favicon.ico);"
281+
style="background-image: url(https://twitter.com/favicon.ico);"
282282
/>
283283
<img
284284
alt=""
285285
class="css-accessibilityImage-9pa8cd"
286286
draggable="false"
287-
src="https://google.com/favicon.ico"
287+
src="https://twitter.com/favicon.ico"
288288
/>
289289
</div>
290290
`;
291291

292-
exports[`components/Image prop "source" is set immediately if the image has already been loaded 2`] = `
292+
exports[`components/Image prop "source" is set immediately if the image was preloaded 1`] = `
293293
<div
294294
class="css-view-175oi2r r-flexBasis-1mlwlqe r-overflow-1udh08x r-zIndex-417010"
295295
>
296296
<div
297297
class="css-view-175oi2r r-backgroundColor-1niwhzg r-backgroundPosition-vvn4in r-backgroundRepeat-u6sd8q r-bottom-1p0dtai r-height-1pi2tsx r-left-1d2f490 r-position-u8s1d r-right-zchlnj r-top-ipm5af r-width-13qz1uu r-zIndex-1wyyakw r-backgroundSize-4gszlv"
298-
style="background-image: url(https://twitter.com/favicon.ico);"
298+
style="background-image: url(https://yahoo.com/favicon.ico);"
299299
/>
300300
<img
301301
alt=""
302302
class="css-accessibilityImage-9pa8cd"
303303
draggable="false"
304-
src="https://twitter.com/favicon.ico"
304+
src="https://yahoo.com/favicon.ico"
305305
/>
306306
</div>
307307
`;
308308

309-
exports[`components/Image prop "source" is set immediately if the image was preloaded 1`] = `
309+
exports[`components/Image prop "source" is set immediately while image is loading and there is no default source 1`] = `
310310
<div
311311
class="css-view-175oi2r r-flexBasis-1mlwlqe r-overflow-1udh08x r-zIndex-417010"
312312
>
313313
<div
314314
class="css-view-175oi2r r-backgroundColor-1niwhzg r-backgroundPosition-vvn4in r-backgroundRepeat-u6sd8q r-bottom-1p0dtai r-height-1pi2tsx r-left-1d2f490 r-position-u8s1d r-right-zchlnj r-top-ipm5af r-width-13qz1uu r-zIndex-1wyyakw r-backgroundSize-4gszlv"
315-
style="background-image: url(https://yahoo.com/favicon.ico);"
315+
style="background-image: url(https://google.com/not-yet-loaded-image.ico);"
316316
/>
317317
<img
318318
alt=""
319319
class="css-accessibilityImage-9pa8cd"
320320
draggable="false"
321-
src="https://yahoo.com/favicon.ico"
321+
src="https://google.com/not-yet-loaded-image.ico"
322322
/>
323323
</div>
324324
`;

packages/react-native-web/src/exports/Image/__tests__/index-test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,8 @@ describe('components/Image', () => {
277277
});
278278
});
279279

280-
test('is not set immediately if the image has not already been loaded', () => {
281-
const uri = 'https://google.com/favicon.ico';
280+
test('is set immediately while image is loading and there is no default source', () => {
281+
const uri = 'https://google.com/not-yet-loaded-image.ico';
282282
const source = { uri };
283283
const { container } = render(<Image source={source} />);
284284
expect(container.firstChild).toMatchSnapshot();

packages/react-native-web/src/exports/Image/index.js

+6-13
Original file line numberDiff line numberDiff line change
@@ -225,24 +225,18 @@ const BaseImage: ImageComponent = React.forwardRef((props, ref) => {
225225
}
226226
}
227227

228-
const [state, updateState] = React.useState(() => {
229-
const uri = resolveAssetUri(source);
230-
if (uri != null) {
231-
const isLoaded = ImageLoader.has(uri);
232-
if (isLoaded) {
233-
return LOADED;
234-
}
235-
}
236-
return IDLE;
237-
});
238-
228+
const [state, updateState] = React.useState(IDLE);
239229
const [layout, updateLayout] = React.useState({});
240230
const hasTextAncestor = React.useContext(TextAncestorContext);
241231
const hiddenImageRef = React.useRef(null);
242232
const filterRef = React.useRef(_filterId++);
243233
const requestRef = React.useRef(null);
234+
const uri = resolveAssetUri(source);
235+
const isCached = uri != null && ImageLoader.has(uri);
244236
const shouldDisplaySource =
245-
state === LOADED || (state === LOADING && defaultSource == null);
237+
state === LOADED ||
238+
isCached ||
239+
(state === LOADING && defaultSource == null);
246240
const [flatStyle, _resizeMode, filter, _tintColor] = getFlatStyle(
247241
style,
248242
blurRadius,
@@ -297,7 +291,6 @@ const BaseImage: ImageComponent = React.forwardRef((props, ref) => {
297291
}
298292

299293
// Image loading
300-
const uri = resolveAssetUri(source);
301294
React.useEffect(() => {
302295
abortPendingRequest();
303296

0 commit comments

Comments
 (0)