Skip to content

Commit 51c85c6

Browse files
authored
Merge pull request #503 from Shopify/fix/283-onError-callback-useImage
Fix/283 on error callback use image
2 parents c36c316 + c454a0b commit 51c85c6

File tree

7 files changed

+72
-35
lines changed

7 files changed

+72
-35
lines changed

example/src/Examples/API/Images.tsx

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,24 @@ const rects = [
2626
];
2727

2828
export const Images = () => {
29+
// Verifies that the error handler for images are working correctly.
30+
useImage(new Uint8Array([0, 0, 0, 255]), (err) => {
31+
if (err.message !== "Could not load data") {
32+
throw new Error(
33+
`Expected error message to be 'Could not load data' - got '${err.message}'`
34+
);
35+
}
36+
});
37+
useImage("https://reactjs.org/invalid.jpg", (err) => {
38+
if (err.message !== "Could not load data") {
39+
throw new Error(
40+
`Expected error message to be 'Could not load data' - got '${err.message}'`
41+
);
42+
}
43+
});
44+
2945
const oslo = useImage(require("../../assets/oslo.jpg"));
30-
if (oslo === null) {
31-
return null;
32-
}
46+
3347
return (
3448
<ScrollView>
3549
{fits.map((fit, i) => (
@@ -47,14 +61,16 @@ export const Images = () => {
4761
height={height}
4862
color="lightblue"
4963
/>
50-
<Image
51-
image={oslo}
52-
x={x}
53-
y={y}
54-
width={width}
55-
height={height}
56-
fit={fit}
57-
/>
64+
{oslo ? (
65+
<Image
66+
image={oslo}
67+
x={x}
68+
y={y}
69+
width={width}
70+
height={height}
71+
fit={fit}
72+
/>
73+
) : null}
5874
</React.Fragment>
5975
);
6076
})}

example/src/Examples/API/SVG.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@ const { width, height } = Dimensions.get("window");
66

77
export const SVG = () => {
88
const svg = useSVG(require("./tiger.svg"));
9-
if (svg === null) {
10-
return null;
11-
}
129
return (
1310
<Canvas style={{ flex: 1 }}>
14-
<ImageSVG svg={svg} x={0} y={0} width={width / 2} height={height / 2} />
11+
{svg ? (
12+
<ImageSVG svg={svg} x={0} y={0} width={width / 2} height={height / 2} />
13+
) : null}
1514
</Canvas>
1615
);
1716
};

package/src/skia/core/Data.ts

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { DependencyList } from "react";
2-
import { useEffect, useState } from "react";
2+
import { useRef, useEffect, useState } from "react";
33
import { Image } from "react-native";
44

55
import { Skia } from "../Skia";
@@ -34,23 +34,39 @@ export const useDataCollection = <T>(
3434

3535
export const useRawData = <T>(
3636
source: DataSource,
37-
factory: (data: Data) => T
37+
factory: (data: Data) => T,
38+
onError?: (err: Error) => void
3839
) => {
3940
const [data, setData] = useState<T | null>(null);
41+
const prevSourceRef = useRef<DataSource>();
4042
useEffect(() => {
41-
if (source instanceof Uint8Array) {
42-
setData(factory(Skia.Data.fromBytes(source)));
43-
} else {
44-
const uri =
45-
typeof source === "string"
46-
? source
47-
: Image.resolveAssetSource(source).uri;
48-
Skia.Data.fromURI(uri).then((d) => setData(factory(d)));
43+
// Track to avoid re-fetching the same data
44+
if (prevSourceRef.current !== source) {
45+
prevSourceRef.current = source;
46+
const factoryWrapper = (data2: Data) => {
47+
const factoryResult = factory(data2);
48+
if (factoryResult === null) {
49+
onError && onError(new Error("Could not load data"));
50+
setData(null);
51+
} else {
52+
setData(factoryResult);
53+
}
54+
};
55+
if (source instanceof Uint8Array) {
56+
factoryWrapper(Skia.Data.fromBytes(source));
57+
} else {
58+
const uri =
59+
typeof source === "string"
60+
? source
61+
: Image.resolveAssetSource(source).uri;
62+
Skia.Data.fromURI(uri).then((d) => factoryWrapper(d));
63+
}
4964
}
50-
}, [factory, source]);
65+
}, [factory, onError, source]);
5166
return data;
5267
};
5368

5469
const identity = (data: Data) => data;
5570

56-
export const useData = (source: DataSource) => useRawData(source, identity);
71+
export const useData = (source: DataSource, onError?: (err: Error) => void) =>
72+
useRawData(source, identity, onError);

package/src/skia/core/Font.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@ import { useTypeface } from "./Typeface";
99
/**
1010
* Returns a Skia Font object
1111
* */
12-
export const useFont = (font: DataSource, size?: number): SkFont | null => {
13-
const typeface = useTypeface(font);
12+
export const useFont = (
13+
font: DataSource,
14+
size?: number,
15+
onError?: (err: Error) => void
16+
): SkFont | null => {
17+
const typeface = useTypeface(font, onError);
1418
return useMemo(() => {
1519
if (typeface === null) {
1620
return null;

package/src/skia/core/Image.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ import { useRawData } from "./Data";
66
/**
77
* Returns a Skia Image object
88
* */
9-
export const useImage = (source: DataSource) =>
10-
useRawData(source, Skia.MakeImageFromEncoded);
9+
export const useImage = (source: DataSource, onError?: (err: Error) => void) =>
10+
useRawData(source, Skia.MakeImageFromEncoded, onError);

package/src/skia/core/SVG.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ import type { DataSource } from "../types";
33

44
import { useRawData } from "./Data";
55

6-
export const useSVG = (source: DataSource) =>
7-
useRawData(source, Skia.SVG.MakeFromData);
6+
export const useSVG = (source: DataSource, onError?: (err: Error) => void) =>
7+
useRawData(source, Skia.SVG.MakeFromData, onError);

package/src/skia/core/Typeface.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,7 @@ import { useRawData } from "./Data";
55
/**
66
* Returns a Skia Typeface object
77
* */
8-
export const useTypeface = (source: DataSource) =>
9-
useRawData(source, Skia.Typeface.MakeFreeTypeFaceFromData);
8+
export const useTypeface = (
9+
source: DataSource,
10+
onError?: (err: Error) => void
11+
) => useRawData(source, Skia.Typeface.MakeFreeTypeFaceFromData, onError);

0 commit comments

Comments
 (0)