Search code examples
javascriptreactjsrustwebassembly

Accessing WASM functions from vanilla JS inside a React App


I am taking my first steps into using WebAssembly functions in JavaScript (inside React).

I know it's probably not the proper way to do this, but I've wrapped my entire app in the exported Rust functions, like this:

import init from 'my-lib'

init().then((wasm) => {
  const root = ReactDOM.createRoot(document.getElementById('root'))
  root.render(
    <React.StrictMode>
      <App wasm={wasm} />
    </React.StrictMode>
  )
})

I then use a React Context to access the wasm object wherever I needed. It works fine. I've written a few Rust functions and replaced some of my code's heavy calculations with them. My CPU usage was cut in half, so of course I wanted to take it further.

My issue is with a non-React JS file that is used in the project. It runs a timer and exports some functions that allow React component to subscribe to different events (this allows me to have a single central timer for the entire application).

I have no idea how to import the WebAssembly functions into that file, because of course I can't use React Contexts there (and the init().then syntax doesn't work). How can I make the functions inside the vanilla JS file access the functions defined in the WASM package?


Solution

  • Since init returns a promise you can just use that promise over and over to make sure you get access to the same return value.

    import init from 'my-lib'
    
    let wasmPromise = null;
    
    export function getWasm(){
      if( !wasmPromise ){
        wasmPromise = init();
      }
    
      return wasmPromise;
    }
    

    You can then use it from wherever you want.

    import { getWasm } from './my-wasm-wrapper'
    
    getWasm().then( wasm => /* whatever */ )
    
    getWasm().then( wasm => /* same wasm as above */ )