-
Notifications
You must be signed in to change notification settings - Fork 39
Open
Description
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
ModelViewercomponent that loads a.glbasset usingreact-native-filament. - Change the
modelPathprop at runtime to a different.glbfile. - Observe that the app throws a
Regular javascript function '' cannot be sharederror 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
.glbto themetro.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/*.glband tried to load them usingAssets.fromModule(require('../assets/models/rhino.glb')).uri
- I moved my assets into
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.
- I served my assets from a local server and downloaded them to the device's
expo-file-system- (Same as above)
- 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.
Metadata
Metadata
Assignees
Labels
No labels