Best practise to remove ShapeDiver view instance from the DOM

I am generating several ShapeDiver models in my front-end. The idea is to remove one window and then generate a new one.

This is how I generate a new window:
api = await new window.SDVApp.ParametricViewer(settings);
If I rerun this command it seems it just pushes new canvases to the DOM without removing the previous one.

So, my questions is, how to remove safely one view instance from the DOM? Basically I am supplying a new ticket to the viewer, so I want to render this new model instead.

Following code example shows you how to load and destroy the viewer.

In the CodePen console (bottom left button to open) you can type in loadViewer to load the viewer and destroyViewer to destroy it again. As you can see, this process can be repeated anytime.

Thanks @pavol, exactly, I am looking for something like this. However, I am getting this error in the console at CodePen:


What message should I get normally?

I get this:

image

It seems it was a WebGL issue in Chrome, I tried in Safari and works ok.
Thanks again, this will be the solution, I just need to implement it to my React app.

1 Like

@pavol I implemented your suggestion into a cleanup function in a React hook, it might help others too who is using React 16+. There might be other solutions too, but this works for me.
My RenderSDScene function renders the SDViewer when the component is mounted or the ticket props is changing, in my case.

  useEffect(() => {
    renderSDScene()
    return () => {
      let result = api.viewports.get();
      api.viewports.destroy(result.getViewportRuntimeId());
      delete window.api
      console.log("SDViewer component was unmounted un cleaned up!")
    }
  }, [props.ticket])
1 Like

Good job @Balazs_Kisfali , thanks for sharing this.

Contributing a bit more on the topic…

I’ve found that destroying viewports does indeed help with unmounting ShapeDiver in the DOM but, it helps to take things further. Simply destroying the viewport can lead to a webGL frame buffer warning plus, if a user is rapidly opening and closing your ShapeDiver component, error messages can appear. Despite the console messages, things may appear to function as expected.

I worry about performance degradation in webGL because of frame buffer issues, lingering contexts… and, if a user is forcing rapid mounts and unmounts, things can break.

I use the following to keep my console and conscience clean:

const useCloseActiveViewports = (api) => {
  const viewports = api.viewports.get();
  // kill all viewports
  // don't want any issues building up webGL contexts
  if (Array.isArray(viewports)) {
    let runtimeIDs = [];
    viewports.forEach((viewport) => {
      runtimeIDs.push(viewport.getViewportRuntimeId());
    });
    runtimeIDs.forEach((runtimeID) => {
      viewer.viewports.destroy(runtimeID);
    });
  } else {
    const runtimeID = viewports.getViewportRuntimeId();
    viewer.viewports.destroy(runtimeID);
  }
}

const useUnmountShapediver = async(api) => {
  if (api) {
    // don't invite error messages by abruptly killing any processes
    await api.scene.pause();
    // set show to false to avoid viewport ghost when creating a new viewport
    // relevant if you're reusing the api object
    await api.updateSettingAsync("scene.show", false);
    // handle the api object
    whateverYouWantToDoWithTheApiObjectFunction();
    // destroy all active viewports
    // ...you could potentially restore a viewport via:
    // .getExtension('WEBGL_lose_context').restoreContext();
    // but this is much more complex...
    // destroying enables you to use ShapeDiver's api function
    // viewport.destroy to "clean-up"
    useCloseActiveViewports(api);
    // Let the parent know child unmount processes are done
    return unmountCallbackFunction();
  }
}

Note: I reuse my api objects - simply destroying them may avoid things breaking on very rapid mount, unmount, mount, unmount… processes but, I’ve also noticed that ShapeDiver may not even pick up on a React re-render if it’s fast. Also, I renamed some things for the forum so there could be a typo up there.

How do you handle removing viewports in the new V3 Viewer API?
You no longer use

api = await new window.SDVApp.ParametricViewer(settings)

to create viewports and sessions so I cannot access

api.viewports.destroy()

Hello @lopa421

In Viewer 3 you similarly have close functions for the viewport and session.

Cheers, Michael