Integration via React library

@reflct/react

Overview

A React library for integrating Reflct 3D scenes into your React apps.

Visit Reflct.app for more information.

Installation

[!IMPORTANT] Compatibility with React 19

Recent releases of React 19 had compatibility issues with our dependencies. So we’ve moved those dependencies to the peer dependencies to resolve the issues. Make sure to install correct versions of peer dependencies to use this package from now on.

To install the package, run:

# Install peer dependencies
npm install three@0.168.0 @react-three/fiber @react-three/drei
 
# Install the package
npm install @reflct/react

or if you’re using yarn:

# Install peer dependencies
yarn add three@0.168.0 @react-three/fiber @react-three/drei
 
# Install the package
yarn add @reflct/react

React 18

If you’re using React 18, you need to install the following peer dependencies:

  • three@0.168.0
  • @react-three/fiber@8
  • @react-three/drei@9
# Install peer dependencies
npm install three@0.168.0 @react-three/fiber@8 @react-three/drei@9
 
# Install the package
npm install @reflct/react

Getting Started

Here’s a basic example of how to use the Viewer component:

import React from "react";
import { Viewer } from "@reflct/react";
 
const Page = () => {
  return <Viewer id={"your-scene-id"} apikey={"your-apikey"} />;
};
 
export default Page;

Advanced Usage

The Viewer component includes props for listening to events and customizing the UI:

<Viewer
  id={"your-scene-id"}
  apikey={"your-apikey"}
  isPreview={true}
  sharedMemoryForWorkers={false}
  sceneRevealMode="gradual"
  className={"your-class-name"}
  // Event handlers
  onLoadStart={() => {}}
  onLoadProgressUpdate={(progress) => {}}
  onLoadComplete={(viewGroups, global) => {}}
  onStateChangeStart={(targetView, targetViewGroup, global) => {}}
  onStateChangeComplete={(currentView, currentViewGroup, global) => {}}
  onError={(error) => {}}
/>

Props

PropTypeDescription
idstringThe unique ID of your scene
apikeystringYour API key
isPreviewbooleanUse a preview version of the scene
sceneRevealModestringThe mode to reveal the scene. ‘gradual’ or ‘instant’
sharedMemoryForWorkersbooleanUse shared memory for workers
classNamestringCustom CSS class for the viewer

Events

EventTypeDescription
onLoadStart() => voidTriggered when the scene starts loading
onLoadProgressUpdate(progress: number) => voidUpdates as the scene loads
onLoadComplete(viewGroups, global) => voidTriggered when the scene is fully loaded
onStateChangeStart(targetView, targetViewGroup, global) => voidTriggered at the start of a state change
onStateChangeComplete(currentView, currentViewGroup, global) => voidTriggered when a state change is complete
onError(error: string) => voidTriggered when an error occurs

Example: Using Events and Metadata

You can use metadata from events to update your application logic, such as state or UI:

import React from "react";
import { Viewer } from "@reflct/react";
import useProductStore from "../stores/product-store";
 
const Page = () => {
  const extractMetadata = (viewGroups, global, key) => {
    return (
      viewGroups[0].views[0].metadata?.[key] ||
      viewGroups[0].metadata?.[key] ||
      global.metadata?.[key]
    );
  };
 
  return (
    <Viewer
      id={sceneId}
      apikey={apikey}
      onLoadComplete={(viewGroups, global) => {
        useProductStore.setState((state) => {
          state.loading = false;
          state.title = extractMetadata(viewGroups, global, "productTitle");
          state.subtitle = extractMetadata(
            viewGroups,
            global,
            "productCategory"
          );
          const price = extractMetadata(viewGroups, global, "price");
          state.price = !isNaN(Number(price)) ? Number(price) : null;
        });
      }}
    />
  );
};

Customizing the UI

You can pass children to customize the viewer’s UI:

<Viewer id={"your-scene-id"} apikey={"your-apikey"}>
  {({
    currentView,
    currentViewGroup,
    global,
    index,
    automode,
    setAutomode,
    isLoading,
    loadProgress,
    nextView,
    prevView,
    summaryImage,
    linkedScenes,
    loadScene,
  }) => <div>Custom Controls</div>}
</Viewer>
PropTypeDescription
currentViewCurrentViewMetadataMetadata for the current view
currentViewGroupViewGroupMetadataMetadata for the current view group
globalGlobalMetadataGlobal scene metadata
indexnumberCurrent view index
automodebooleanIs auto mode enabled?
setAutomodefunctionFunction to toggle auto mode
isLoadingbooleanIs the scene loading?
loadProgressnumberThe progress of the scene loading
nextViewfunctionFunction to navigate to the next view
prevViewfunctionFunction to navigate to the previous view
summaryImagestring or nullThe summary image of the scene
linkedScenesarrayThe linked scenes of the scene
loadScenefunctionThe function to load linked scene

If you wish to customise the UI of the hitpoints, you can do that by giving the hitPoint prop.

<Viewer
  id={"your-scene-id"}
  apikey={"your-apikey"}
  hitPoint={(state: {
    index: number,
    isSelected: boolean,
    inCurrentGroup: boolean,
    select: () => void,
  }) => <button onClick={state.select}>Hitpoint</button>}
/>
PropsTypeDescription
indexnumberThe index of the hitpoint
isSelectedbooleanWhether the hitpoint is selected
inCurrentGroupbooleanWhether the hitpoint is in the current view group
selectfunction (() => void)The function to select the hitpoint

CORS Issues and SharedArrayBuffer

This package uses SharedArrayBuffer by default for improved performance. However, this may cause CORS issues in browser environments.

Security Requirements

To avoid CORS issues, ensure your document operates in a secure context. Add the following headers to your server configuration:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

For more details, refer to the MDN documentation.

Disabling SharedArrayBuffer

If you cannot configure your server, disable SharedArrayBuffer by setting the sharedMemoryForWorkers prop to false:

<Viewer
  id={"your-scene-id"}
  apikey={"your-apikey"}
  sharedMemoryForWorkers={false}
/>