Skip to main content

Using viewers with React

If you would like to use FSI Viewer or any other NeptuneLabs viewer with React, we advise you to create a FSI Component that ensures that the viewers are initialised correctly.

If you do simply embed the viewers as a component, it might still work, but will cause problems since the viewer will then be initialised in the Shadow DOM and changes will not be detected.

All viewers shown in this documentation are embedded using those FSIComponents.

Creating the FSI Component

This is the code used in the corresponding fsiComponent.jsx:

import React from 'react'
import { createElement } from 'react'

class FSIComponent extends React.Component {

constructor(props) {
super(props)
this.ref = React.createRef()
}

getIgnoredProps = function(){
return {
"children": 1,
"style": 1,
"id": 1,
"data-fsi-id": 1
}
}

getDefaultParameters(){
return {
ref: this.ref,
autoInit: false,
skin: "black-flat"
}
}

destroyInstance(){
const instance = this.ref.current

if (
(
typeof instance.getInitDone !== "function" ||
instance.getInitDone()
) &&
typeof instance.destroy === "function"
){
instance.destroy()
}
}

initInstance(){
const instance = this.ref.current
if (
typeof instance.init === "function" &&
instance.init(instance, this.getParameters()) &&
typeof instance.start === "function"
){
instance.start()
}
}

getParameters(){
return {...this.getDefaultParameters(), ...this.props, ...{tagName:null}}
}

componentWillUnmount() {
this.destroyInstance()
}

shouldComponentUpdate(nextProps){
const toIgnore = this.getIgnoredProps()

const changedProps = Object.keys(nextProps).filter(key => {
return !toIgnore[key] && nextProps[key] !== this.props[key]
})

return (changedProps.length > 0)
}

componentDidUpdate(prevProps, prevState) {
this.destroyInstance()
this.initInstance()
}

componentDidMount() {
this.initInstance()
}

render() {
return createElement(this.props.tagName, this.getParameters())
}
}

export default FSIComponent

With this, you ensure that you will detect if the component mounts, umounts or updates and then set correctly if the instance should be initialised or destroyed.

Using FSIComponent

You can use this FSIComponent in two ways, either directly in the files or as a seperated component. The latter is recommended for more complex viewer combinations as a FSI Showcase made from FSI Viewer and FSI Thumbbar.

Directly in file

Import the newly created FSIComponent from the corresponding directory, e.g.:

import FSIComponent from '/src/components/fsiComponent';

Add the FSIComponent on the place where you want to have the viewer displayed:

<FSIComponent tagName="fsi-viewer"
dir={"images/samples/notebook"}
width={"100%"}
skin={"white"}
plugins={"resize,fullScreen"}
adaptiveuisize={false}
forceinplacezoom={true}
videosource={"[static]assets/notebook/notebook"}
pellets={false}
videospindirection={"left"}
autodisablepointeractions={true}
/>

The tagName defines the viewer used, e.g. fsi-viewer, fsi-touchzoom, fsi-imagegrid.

As a separate component

For FSI Showcase, a separate component which can then be imported could look like this:

import React from "react"
import FSIComponent from './fsiComponent'

const Showcase = ({ }) => {
return (
<>
<div style={{display: 'flex', flexDirection: 'column', flexWrap: 'nowrap', width: '100%', height: '600px'}} id="fsi-showcase-1689840468239-713615">

<FSIComponent tagName="fsi-viewer" id={"fsi-viewer-1689840468239-39461"}
style={{width:'100%', height:'calc(100% - 160px)', flex: '1 1 100%'}}
plugins={"resize,fullScreen"}
fullScreenElement={"fsi-showcase-1689840468239-713615"} skin={"white"}/>

<FSIComponent tagName="fsi-thumbbar" viewerSelector={"fsi-viewer-1689840468239-39461"} style={{flex: '0 0 160px'}}
width={"100%"} height={"160px"} dir={"images/samples/showcase/tutorial"}
vertical={false} elementWidth={"240px"} elementSpacing={"4px"}
alignment={0.5} paddingTop={0} paddingBottom={"4px"}/>
</div>
</>
);
};

export default Showcase;