I've been having difficulty using react-native expo and react-native-filament to display 3d models in succession within the same display component<ModelViewer>.
When changing the source prop of a <Model /> component from react-native-filament, React Native throws the following warning and eventually crashes on subsequent model loads:
Warning: Error: Regular javascript function '' cannot be shared.
Try decorating the function with the 'worklet' keyword to allow the javascript function to be used as a worklet.
This occurs when re-rendering my ModelViewer component which wraps FilamentScene, FilamentView, and Model to display a different .glb file.
Environment
| Library |
Version |
react-native |
0.79.6 |
expo |
53.0.23 |
react-native-filament |
1.8.0 |
react-native-reanimated |
3.17.4 |
| Device |
iOS Simulator (M4 IPad Pro) |
Steps to Reproduce
- Create a
ModelViewer component that loads a .glb asset using react-native-filament.
- Change the
modelPath prop at runtime to a different .glb file.
- Observe that the app throws a
Regular javascript function '' cannot be shared error during the update cycle.
// ModelViewer.tsx
import React, { useState, useEffect } from "react";
import { FilamentView, Model } from "react-native-filament";
interface ModelViewerProps {
modelPath: string;
key?: string;
}
export default function ModelViewer({ modelPath, key }: ModelViewerProps) {
const [actualModelPath, setActualModelPath] = useState<string>("");
const [isLoading, setIsLoading] = useState(true);
const [hasError, setHasError] = useState(false);
useEffect(() => {
setActualModelPath(modelPath);
setIsLoading(false);
}, [modelPath]);
if (isLoading || hasError) return null;
return (
<FilamentScene key={key}>
<FilamentView key={key} style={styles.filamentView}>
<DefaultLight />
<Model
key={key}
translate={[0, 0, -5]}
source={{uri: actualModelPath}}
/>
<Camera />
</FilamentView>
</FilamentScene>
);
}
Then render it in a parent component and update the prop:
// Parent.tsx
import {Asset} from 'expo-asset'
const [selectedModel, setSelectedModel] = Asset.fromModule('../assets/model/watch.glb').uri;
return (
<>
<Button title="Switch" onPress={() => setSelectedModel(Asset.fromModule('../assets/model/rhino.glb').uri} />
<ModelViewer modelPath={selectedModel} />
</>
);
Fix Attempts
- Adding to
.glb to the metro.config.js
- I thought this might be an issue related to how I was loading my .glb assets, and the speed at which I was accessing them, so I modified my code to use different file system libraries.
expo-asset
- I moved my assets into
/assets/models/*.glb and tried to load them using Assets.fromModule(require('../assets/models/rhino.glb')).uri
react-native-fs
- I served my assets from a local server and downloaded them to the device's
Documents/ folder and downloaded them at runtime.
expo-file-system
- Reducing the file of the .glb files. This worked partially. However, I found that though the 'worklet' issue wouldn't appear, there would be a file read error saying something like:
unexpected character ‘’ error
- Wrapping the Model in a 'worklet' function
- Downgrading my dependencies as per NSException crash
Minimal Reproduction Repo
You can reproduce it by cloning this example repo and switching between two .glb files using a state toggle.
I've been having difficulty using
react-nativeexpoandreact-native-filamentto display 3d models in succession within the same display component<ModelViewer>.When changing the
sourceprop of a<Model />component fromreact-native-filament, React Native throws the following warning and eventually crashes on subsequent model loads:This occurs when re-rendering my
ModelViewercomponent which wraps FilamentScene, FilamentView, and Model to display a different.glbfile.Environment
react-nativeexporeact-native-filamentreact-native-reanimatedSteps to Reproduce
ModelViewercomponent that loads a.glbasset usingreact-native-filament.modelPathprop at runtime to a different.glbfile.Regular javascript function '' cannot be sharederror during the update cycle.Then render it in a parent component and update the prop:
Fix Attempts
.glbto themetro.config.jsexpo-asset/assets/models/*.glband tried to load them usingAssets.fromModule(require('../assets/models/rhino.glb')).urireact-native-fsDocuments/folder and downloaded them at runtime.expo-file-systemunexpected character ‘’ errorMinimal Reproduction Repo
You can reproduce it by cloning this example repo and switching between two
.glbfiles using a state toggle.