From 3c660e2ad7df4815ef1735acc262ae52e2cae8cf Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Sat, 24 Jun 2017 07:37:29 -0700 Subject: [PATCH] [fix] SSR of Image renders source When rendered on the server, images now include the 'src' and will be downloaded by the browser rather than waiting for the client-side JS to initiate image loading. Fix #543 --- src/components/Image/__tests__/index-test.js | 11 +++++++++++ src/components/Image/index.js | 13 +++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/components/Image/__tests__/index-test.js b/src/components/Image/__tests__/index-test.js index a9c90326..8b78aec9 100644 --- a/src/components/Image/__tests__/index-test.js +++ b/src/components/Image/__tests__/index-test.js @@ -1,10 +1,12 @@ /* eslint-env jasmine, jest */ +import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment'; import Image from '../'; import ImageUriCache from '../ImageUriCache'; import React from 'react'; import { mount, render } from 'enzyme'; +const originalCanUseDOM = ExecutionEnvironment.canUseDOM; const originalImage = window.Image; describe('components/Image', () => { @@ -113,6 +115,15 @@ describe('components/Image', () => { ImageUriCache.remove(uriTwo); expect(component.render().find('img').attr('src')).toBe(uriTwo); }); + + test('is set immediately when rendered on the server', () => { + ExecutionEnvironment.canUseDOM = false; + const uri = 'https://google.com/favicon.ico'; + const component = render(); + expect(component.find('img').attr('src')).toBe(uri); + expect(ImageUriCache.has(uri)).toBe(true); + ExecutionEnvironment.canUseDOM = originalCanUseDOM; + }); }); describe('prop "style"', () => { diff --git a/src/components/Image/index.js b/src/components/Image/index.js index d6d29cfa..548c2812 100644 --- a/src/components/Image/index.js +++ b/src/components/Image/index.js @@ -11,6 +11,7 @@ */ import applyNativeMethods from '../../modules/applyNativeMethods'; +import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment'; import createDOMElement from '../../modules/createDOMElement'; import ImageLoader from '../../modules/ImageLoader'; import ImageResizeMode from './ImageResizeMode'; @@ -41,8 +42,8 @@ const ImageSourcePropType = oneOfType([ string ]); -const getImageState = (uri, isPreviouslyLoaded) => { - return isPreviouslyLoaded ? STATUS_LOADED : uri ? STATUS_PENDING : STATUS_IDLE; +const getImageState = (uri, shouldDisplaySource) => { + return shouldDisplaySource ? STATUS_LOADED : uri ? STATUS_PENDING : STATUS_IDLE; }; const resolveAssetDimensions = source => { @@ -111,10 +112,10 @@ class Image extends Component { super(props, context); // If an image has been loaded before, render it immediately const uri = resolveAssetSource(props.source); - const isPreviouslyLoaded = ImageUriCache.has(uri); - this.state = { shouldDisplaySource: isPreviouslyLoaded }; - this._imageState = getImageState(uri, isPreviouslyLoaded); - isPreviouslyLoaded && ImageUriCache.add(uri); + const shouldDisplaySource = ImageUriCache.has(uri) || !canUseDOM; + this.state = { shouldDisplaySource }; + this._imageState = getImageState(uri, shouldDisplaySource); + shouldDisplaySource && ImageUriCache.add(uri); } componentDidMount() {