Skip to content

AppProvider

The React root for an App: it captures the instance once and owns its init, mount, unmount and destroy. Where the App sits in the module tree is on Modules; this page is the API surface.

Signature

ts
AppProvider(props: AppProviderProps): JSX.Element

type AppProviderProps = {
    app: App | (() => App)
    children?: ReactNode
}

Only an App is accepted - a Module is not assignable.

app

tsx
import { App, AppProvider } from "@remodulo/react"

export const app = new App({ providers: [OrdersApi] })

function Root() {
    return (
        <AppProvider app={app}>
            <OrdersPage />
        </AppProvider>
    )
}

// The factory form: built inside React, called on the first render only.
function FactoryRoot() {
    return (
        <AppProvider app={() => new App({ providers: [OrdersApi] })}>
            <OrdersPage />
        </AppProvider>
    )
}

Root hands in an app constructed outside React, which is the usual form. FactoryRoot builds one inside React instead, for an App that cannot exist before the render that needs it.

The instance is captured on the first render. It is held in state from then on, so re-rendering the parent never touches it.

Replacing it throws. Passing a different App instance to the same provider:

AppProvider does not support replacing its App instance

The factory runs once. It is called on the first render only, so a fresh arrow function on every render is free - the check above does not apply to the factory form.

Lifecycle

Init runs during render. A freshly constructed App is initialized by the provider before its children render, not in an effect. An init that throws is logged as App failed to initialize: and re-thrown at the render that provided it.

Mount, unmount and destroy belong to the provider. Mount runs on the effect after commit, unmount on that effect's cleanup, and destroy one macrotask later - a re-mount inside that tick cancels it and revives the same instances.

A spent App cannot be provided again. Rendering a provider around an App whose init already failed throws App failed to initialize.; around one that has been destroyed, App was destroyed. Provide a fresh App. Both mean the same thing: construct a new App.

What children see

The App is the parent module for everything below it, until a boundary opens a scope of its own. The rebuild from useModuleContext is a no-op under a bare AppProvider: the App has no parent to be rebuilt under.

Where to go next

Guides

Reference

MIT licensed.