react-native-skia
react-native-skia copied to clipboard
React Native Skia on Web - Unable to load with multiple tabs open at once
Description
Using WithSkiaWeb, having more then one tab opened at once, fallback attribute will trigger
I've also checked that canvaskit.wasm is correctly fetching in duplicated tab, so I guess it's just issue with WithSkiaWeb
React Native Skia Version
2.2.12
React Native Version
0.81.4
Using New Architecture
- [x] Enabled
Steps to Reproduce
- Use WithSkiaWeb
import '@expo/metro-runtime'
import { WithSkiaWeb } from '@shopify/react-native-skia/lib/module/web';
import { fontsConfig } from './fontsConfig';
import { useFonts } from 'expo-font';
import UILoaderText from './components/UI/UILoaderText';
export default function App() {
let location = window.location.origin
/* -------------------------- 2. Load Project Font -------------------------- */
const [fontsLoaded] = useFonts(fontsConfig);
if (!fontsLoaded) return <UILoaderText text='Fonts' />;
/* -------------------------------------------------------------------------- */
return (
<WithSkiaWeb
getComponent={() => import("./AppCore")}
opts={{
locateFile: (file) => `${location}/${file}?v=${Date.now()}`
}}
fallback={<UILoaderText text='Loading skia web...' />}
/>
);
}
- Duplicate Tab in browser
- Unable to pass Loading skia web
Snack, Code Example, Screenshot, or Link to Repository
import '@expo/metro-runtime'
import { WithSkiaWeb } from '@shopify/react-native-skia/lib/module/web';
import { fontsConfig } from './fontsConfig';
import { useFonts } from 'expo-font';
import UILoaderText from './components/UI/UILoaderText';
export default function App() {
let location = window.location.origin
/* -------------------------- 2. Load Project Font -------------------------- */
const [fontsLoaded] = useFonts(fontsConfig);
if (!fontsLoaded) return <UILoaderText text='Fonts' />;
/* -------------------------------------------------------------------------- */
return (
<WithSkiaWeb
getComponent={() => import("./AppCore")}
opts={{
locateFile: (file) => `${location}/${file}?v=${Date.now()}`
}}
fallback={<UILoaderText text='Loading skia web...' />}
/>
);
}
I fixed this using creating own UIWithSkiaWeb :
import React, { useEffect, useState } from "react";
import { View, Text } from "react-native";
import UILoaderText from "./UILoaderText";
interface UIWithSkiaWebProps {
children: React.ReactNode;
version?: string; // 0.40.0
}
export default function UIWithSkiaWeb({ children, version = "0.40.0" }: UIWithSkiaWebProps) {
const [ready, setReady] = useState(false);
useEffect(() => {
if (typeof window === "undefined") return;
const CDN = `https://cdnjs.cloudflare.com/ajax/libs/canvaskit-wasm/${version}/`;
if ((window as any).CanvasKit) { /* If canva exists */
setReady(true);
return;
}
const script = document.createElement("script");
script.src = CDN + "canvaskit.js";
script.async = true;
script.onload = () => {
const CanvasKitInit = (window as any).CanvasKitInit;
if (!CanvasKitInit) {
console.error("CanvasKitInit not found after loading script.");
return;
}
(window as any).CanvasKitPromise = CanvasKitInit({
locateFile: (file: string) => CDN + file,
});
(window as any).CanvasKitPromise.then((ck: any) => {
(window as any).CanvasKit = ck;
setReady(true);
});
};
document.body.appendChild(script);
return () => {
script.remove();
};
}, [version]);
if (!ready) {
return <UILoaderText text={"Loading skia web..."} />
}
return <>{children}</>;
}
Alternative add in index.html :
<script src="https://unpkg.com/[email protected]/bin/canvaskit.js" ></script>
<script>
window.CanvasKitPromise = CanvasKitInit({
locateFile: (f) =>
'https://unpkg.com/[email protected]/bin/' + f,
});
window.CanvasKitPromise.then((ck) => {
window.CanvasKit = ck;
});
</script>