[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
This commit is contained in:
Nicolas Gallagher
2017-06-24 07:37:29 -07:00
parent e9101abefe
commit 3c660e2ad7
2 changed files with 18 additions and 6 deletions

View File

@@ -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(<Image source={{ uri }} />);
expect(component.find('img').attr('src')).toBe(uri);
expect(ImageUriCache.has(uri)).toBe(true);
ExecutionEnvironment.canUseDOM = originalCanUseDOM;
});
});
describe('prop "style"', () => {

View File

@@ -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() {