Declarative WebAssembly instantiation for React
You can install react-wasm using npm:
npm install --save react-wasmIf you aren't using npm in your project, you can include reactWasm using UMD build in the dist folder with <script> tag.
Once you have installed react-wasm, supposing a CommonJS environment, you can import and use it in this way:
import Wasm from "react-wasm";
// supposing an "add.wasm" module that exports a single function "add"
const ExampleComponent = () => (
  <Wasm url="/add.wasm">
    {({ loading, error, data }) => {
      if (loading) return "Loading...";
      if (error) return "An error has occurred";
      const { module, instance } = data;
      return <div>1 + 2 = {instance.exports.add(1, 2)}</div>;
    }}
  </Wasm>
);Since react-wasm uses the latest version of React, a useWasm hook is available:
import { useWasm } from "react-wasm";
// supposing an "add.wasm" module that exports a single function "add"
const ExampleComponent = () => {
  const {
    loading,
    error,
    data
  } = useWasm({
    url: '/add.wasm'
  });
  if (loading) return "Loading...";
  if (error) return "An error has occurred";
  const { module, instance } = data;
  return <div>1 + 2 = {instance.exports.add(1, 2)}</div>;
};It's also possible to use the library using the HoC approach by importing the named withWasm function:
import { withWasm } from "react-wasm";
// supposing an "add.wasm" module that exports a single function "add"
const ExampleComponent = ({ loading, error, data }) => {
  if (loading) return "Loading...";
  if (error) return "An error has occurred";
  const { module, instance } = data;
  return <div>1 + 2 = {instance.exports.add(1, 2)}</div>;
};
// with a config object
const withAdd = withWasm({ url: "/add.wasm " });
const EnhancedExample = withAdd(ExampleComponent);
const App = () => <EnhancedExample />;
// with the "url" prop
const EnhancedExample = withWasm()(ExampleComponent);
const App = () => <EnhancedExample url="/add.wasm" />;The second argument of the withWasm function is a props mapper. If you want to customize the information your child
component will receive from the underlying Wasm component, you can do:
const mapToChild = ({ loading, error, data }) => ({
  hasLoaded: !loading,
  hasError: !!error,
  add: data && data.instance.add
});
const withAdd = withWasm({ url: "/add.wasm " }, mapToChild);
const EnhancedExample = withAdd(ExampleComponent);
const App = () => <EnhancedExample />;type WasmConfig = {
  // you can instantiate modules using a URL
  // or directly a BufferSource (TypedArray or ArrayBuffer)
  url?: string,
  bufferSource?: BufferSource,
  // An optional object containing the values to be imported into the newly-created Instance
  // such as functions or WebAssembly.Memory objects.
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate#Syntax
  importObject?: {},
};
type WasmResult = {
  loading: boolean,
  error: ?Error,
  data: ?{
    module: WebAssembly.Module,
    instance: WebAssembly.Instance
  }
};
type WasmProps = {
  ...$Exact<WasmConfig>,
  children: (renderProps: WasmResult) => React.Node
};
withWasm(
  config?: WasmConfig,
  mapProps?: ({ loading, error, data }: WasmResult) => Props
): (Component: React.ComponentType) => React.ComponentType
useWasm(config?: WasmConfig): WasmResult;react-wasm uses fetch and obviously WebAssembly APIs, they are broadly supported by major browser engines but you would like to polyfill them to support old versions.
if (!window.fetch || !window.WebAssembly) {
    ...
} else {
    ...
}This project adheres to Semantic Versioning.
Every release, along with the migration instructions, is documented on the Github Releases page.
Matteo Basso
Copyright (c) 2019, Matteo Basso.
react-wasm source code is licensed under the MIT License.