Skip to content

Commit c0fd0c4

Browse files
andrewdacenkofacebook-github-bot
authored andcommitted
Handle empty source for Image
Summary: Changelog: [Android] When source / src is not set for Image we still set `source` native prop with array of undefined. This will warn users when they do not have source set i.e null, undefined, `''` Differential Revision: D79570377
1 parent 47c7521 commit c0fd0c4

3 files changed

Lines changed: 55 additions & 37 deletions

File tree

packages/react-native/Libraries/Image/Image.android.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,7 @@ let BaseImage: AbstractImageAndroid = ({
135135
ref?: React.RefSetter<HostInstance>,
136136
...ImageProps,
137137
}) => {
138-
let source = getImageSourcesFromImageProps(props) || {
139-
uri: undefined,
140-
width: undefined,
141-
height: undefined,
142-
};
138+
let source = getImageSourcesFromImageProps(props) || undefined;
143139
const defaultSource = resolveAssetSource(props.defaultSource);
144140
const loadingIndicatorSource = resolveAssetSource(
145141
props.loadingIndicatorSource,
@@ -162,6 +158,9 @@ let BaseImage: AbstractImageAndroid = ({
162158
if (Array.isArray(source)) {
163159
style = [styles.base, props.style];
164160
sources = source;
161+
} else if (source == null) {
162+
console.warn('source should not be empty');
163+
sources = source;
165164
} else {
166165
const {uri} = source;
167166
if (uri === '') {

packages/react-native/Libraries/Image/ImageSourceUtils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export function getImageSourcesFromImageProps(
7171
}
7272

7373
sources = sourceList;
74-
} else if (src != null) {
74+
} else if (src != null && src !== '') {
7575
sources = [{uri: src, headers: headers, width, height}];
7676
} else if (source != null && source.uri && Object.keys(headers).length > 0) {
7777
sources = [{...source, headers}];

packages/react-native/Libraries/Image/__tests__/Image-itest.js

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,40 +19,17 @@ import {Image} from 'react-native';
1919
import ensureInstance from 'react-native/src/private/__tests__/utilities/ensureInstance';
2020
import ReactNativeElement from 'react-native/src/private/webapis/dom/nodes/ReactNativeElement';
2121

22+
const LOGO_SOURCE = {uri: 'https://reactnative.dev/img/tiny_logo.png'};
23+
2224
describe('<Image>', () => {
2325
describe('props', () => {
24-
it('renders an empty element when there are no props', () => {
25-
const root = Fantom.createRoot();
26-
27-
Fantom.runTask(() => {
28-
root.render(<Image />);
29-
});
30-
31-
expect(
32-
root.getRenderedOutput({includeLayoutMetrics: true}).toJSX(),
33-
).toEqual(
34-
<rn-image
35-
layoutMetrics-borderWidth="{top:0,right:0,bottom:0,left:0}"
36-
layoutMetrics-contentInsets="{top:0,right:0,bottom:0,left:0}"
37-
layoutMetrics-displayType="Flex"
38-
layoutMetrics-frame="{x:0,y:0,width:390,height:0}"
39-
layoutMetrics-layoutDirection="LeftToRight"
40-
layoutMetrics-overflowInset="{top:0,right:0,bottom:0,left:0}"
41-
layoutMetrics-pointScaleFactor="3"
42-
overflow="hidden"
43-
source-scale="1"
44-
source-type="remote"
45-
/>,
46-
);
47-
});
48-
4926
describe('accessibility', () => {
5027
describe('accessible', () => {
5128
it('indicates that image is an accessibility element', () => {
5229
const root = Fantom.createRoot();
5330

5431
Fantom.runTask(() => {
55-
root.render(<Image accessible={true} />);
32+
root.render(<Image accessible={true} source={LOGO_SOURCE} />);
5633
});
5734

5835
expect(
@@ -66,7 +43,12 @@ describe('<Image>', () => {
6643
const root = Fantom.createRoot();
6744

6845
Fantom.runTask(() => {
69-
root.render(<Image accessibilityLabel="React Native Logo" />);
46+
root.render(
47+
<Image
48+
accessibilityLabel="React Native Logo"
49+
source={LOGO_SOURCE}
50+
/>,
51+
);
7052
});
7153

7254
expect(
@@ -80,7 +62,7 @@ describe('<Image>', () => {
8062
const root = Fantom.createRoot();
8163

8264
Fantom.runTask(() => {
83-
root.render(<Image alt="React Native Logo" />);
65+
root.render(<Image alt="React Native Logo" source={LOGO_SOURCE} />);
8466
});
8567

8668
expect(root.getRenderedOutput({props: ['^access']}).toJSX()).toEqual(
@@ -99,6 +81,7 @@ describe('<Image>', () => {
9981
<Image
10082
alt="React Native Logo"
10183
accessibilityLabel="React Native"
84+
source={LOGO_SOURCE}
10285
/>,
10386
);
10487
});
@@ -115,14 +98,50 @@ describe('<Image>', () => {
11598
const root = Fantom.createRoot();
11699

117100
Fantom.runTask(() => {
118-
root.render(<Image blurRadius={10} />);
101+
root.render(<Image blurRadius={10} source={LOGO_SOURCE} />);
119102
});
120103

121104
expect(root.getRenderedOutput({props: ['blurRadius']}).toJSX()).toEqual(
122105
<rn-image blurRadius="10" />,
123106
);
124107
});
125108
});
109+
110+
describe('src', () => {
111+
let originalConsoleWarn;
112+
beforeEach(() => {
113+
originalConsoleWarn = console.warn;
114+
// $FlowExpectedError[cannot-write]
115+
console.warn = jest.fn();
116+
});
117+
118+
afterEach(() => {
119+
// $FlowExpectedError[cannot-write]
120+
console.warn = originalConsoleWarn;
121+
});
122+
123+
it('should warn if no source is provided', () => {
124+
const root = Fantom.createRoot();
125+
126+
Fantom.runTask(() => {
127+
root.render(<Image />);
128+
});
129+
130+
expect(console.warn).toHaveBeenCalledTimes(1);
131+
expect(console.warn).toHaveBeenCalledWith('source should not be empty');
132+
});
133+
134+
it('should warn if src is empty', () => {
135+
const root = Fantom.createRoot();
136+
137+
Fantom.runTask(() => {
138+
root.render(<Image src="" />);
139+
});
140+
141+
expect(console.warn).toHaveBeenCalledTimes(1);
142+
expect(console.warn).toHaveBeenCalledWith('source should not be empty');
143+
});
144+
});
126145
});
127146

128147
describe('ref', () => {
@@ -133,7 +152,7 @@ describe('<Image>', () => {
133152
const root = Fantom.createRoot();
134153

135154
Fantom.runTask(() => {
136-
root.render(<Image ref={elementRef} />);
155+
root.render(<Image ref={elementRef} source={LOGO_SOURCE} />);
137156
});
138157

139158
expect(elementRef.current).toBeInstanceOf(ReactNativeElement);
@@ -145,7 +164,7 @@ describe('<Image>', () => {
145164
const root = Fantom.createRoot();
146165

147166
Fantom.runTask(() => {
148-
root.render(<Image ref={elementRef} />);
167+
root.render(<Image ref={elementRef} source={LOGO_SOURCE} />);
149168
});
150169

151170
const element = ensureInstance(elementRef.current, ReactNativeElement);

0 commit comments

Comments
 (0)