Implementing a custom loading screen in react

Hello,

I’m having trouble wrapping my head around the custom loading ui within a react Babylon app. Ideally, I’d like to display a FC before the scene loads and hide it when it has been completely loaded. I thought I could accomplish this by following the tutorial found within the docs and using a ref to either create an element or, replacing the loadingScreenDiv with the component itself and both failed.

Any ideas?

1 Like

Adding @brianzinn a React expert as he might already have done similar things.

I have promisified the SceneLoader - if you want to go to the trouble of throwing that promise then you can wrap it in a Suspense, but likely easiest is just to update loading progress via state mgmt like zustand.

Here’s how I promisified the SceneLoader:
react-babylonjs/useSceneLoader.tsx at master · brianzinn/react-babylonjs (github.com)

That file is tsx, because I am using ContextProvider to capture the progress to send to the Suspense fallback. If you just want to show the progress and hide then you can just hook into progress events and flow through a UI.

What are you using as an example - maybe I can make a code sandbox to demonstrate?

1 Like

Thank you for the swift response!

First I made a functional component:


export default function LoadingScreen() {
    return(
        <div className="loadingScreen">
            <div className="loadingText">
                <h1>Loading</h1>
                <hr />
                <h3>Experiencing Problems? Contact us at support@hastiludes.com</h3>
            </div>
        </div>
    );
};

then I tried to implement the tutorial given like so with the component

function customLoadingScreen() {
      console.log("customLoadingScreen creation")
    }
    customLoadingScreen.prototype.displayLoadingUI = function () {
      console.log("customLoadingScreen loading")
      return(
        <LoadingScreen />
      )
    };
  customLoadingScreen.prototype.hideLoadingUI = function () {
      console.log("customLoadingScreen loaded")
      return(
        <LoadingScreen style = {{display: 'none'}} />
      )
  };
  var loadingScreen = new customLoadingScreen();
  engine.loadingScreen = loadingScreen;

The loadingScreen setter needs an ILoadingScreen implementation. It could be anything that implements state changes:

class CustomLoadingScreen implements ILoadingScreen {
  
  constructor(public store: YourStoreDefinition) {}

  public displayLoadingUI() {
     store.show();
  }

  public hideLoadingUI() {
    store.hide();
  }
}

Creating Custom Loading Screens | Babylon.js Documentation (babylonjs.com)

The store would be something connected to perhaps zustand state management to show/hide your modal. You definitely cannot return a FC from those functions - you need to instead in those functions implement the behaviour (or state changes) to carry out. If you look at the source in the link above the methods are just setting the text or hiding a div. You would be able to do that with a useRef() hook, but it’s better to let the renderer handle the DOM changes for you.

If you still can’t figure it out - I can make a demo tomorrow. Cheers.

1 Like

Thanks, I watched a zustand tutorial and I’m still having a bit of trouble integrating it with ts. Would show() and hide() just need to be values that add and then remove display:none?

Certainly that is one way. I looked a bit more at the purpose of the Custom Loading Screen and then I noticed that you need to call it on your own with engine.displayLoadingUI(), so it seems to be rather contrived and unnecessary level of indirection unless I missed something entirely. You can build reactive components that will do that easily via state.

Here is an example:
floral-water-els13w - CodeSandbox

Whenever a model is loading I show that loading dialog. You can basically set the state to loaded when you want on your own. I thought the Engine would automatically call that method on the loading screen when assets were being loaded - I think that is something separate and I haven’t look at that in a while.

Can you explain more your use case and then probably a better solution will become evident. I can think if you are using Asset Manager to just have that mean your scene is ready. Cheers.