@userkit/react-mount
v0.7.0
Published
Draw UserKit's components in a React app that loads widget.js from the CDN: the page's React, none of ours, and the component bundle still fetched on demand.
Downloads
0
Maintainers
Readme
@userkit/react-mount
UserKit's components in a React app that loads the script from the CDN.
npm i @userkit/react-mountimport { Banner, OnboardingChecklist } from "@userkit/react-mount";
<OnboardingChecklist props={{ slot: "dashboard", onStepAction: go }} />
<Banner props={{ slot: "billing" }} />The page keeps its <script src="https://cdn.userkit.dev/widget.js">. This
package is the bridge, and nothing else — it draws no UI of its own.
Which package is this
Three ways to put a <Banner /> on a page, and they are not interchangeable:
| | React in your bundle | Components in your bundle | Needs a build |
|---|---|---|---|
| @userkit/react | yours | yes | yes |
| widget.js alone | ours, a second copy | no — CDN, on demand | no |
| this | yours | no — CDN, on demand | yes |
@userkit/react is the right answer for most apps: real components, your
React, tree-shaken. Reach for this one when you have React and specifically
want the components off the CDN — so the bundle does not grow, and a fix
reaches the page without a redeploy.
It adds no runtime dependency. @userkit/js is a dependency for its types
only; every import is import type and is erased at build, which a test in
this package enforces rather than promises.
What it handles
- When the script arrives. The tag is
deferred and React does not wait for it, so the component draws its host element and mounts as soon as the loader announces itself. No pollingwindow.UserKiton a timer. - Props that change. Handed over on every render whose values actually changed, as a re-render rather than a remount — a half-filled form survives it. No stringified key.
- Callbacks. An inline arrow rebuilt each render is read fresh. No ref.
- Leaving early. Unmounting before the component bundle has landed cancels the mount instead of stranding it in a node React already dropped.
- A loader older than this package. Warns and leaves the page standing.
API
<UserKitMount name props className style id />
<UserKitMount name="PricingTable" props={{ onSelected: (price) => buy(price) }} />name is any component @userkit/react exports — the same name you would
write in data-userkit, so a page that later adopts a build renames nothing.
props is typed loosely, because this package deliberately does not depend on
@userkit/react, where the prop types live. A project that has it as a
devDependency can name them at the call site:
import type { SignInProps } from "@userkit/react";
<UserKitMount<SignInProps> name="SignIn" props={{ providers: ["google"] }} />The per-component wrappers
One per name — <SignIn />, <Banner />, <NotificationBell />, … — taking
the same props minus name.
useUserKitEmbed()
window.UserKit once it exists, null before and on the server. Use it for
the imperative half:
const userkit = useUserKitEmbed();
<button onClick={() => userkit?.show()}>Suporte</button>;What it does not do
The guards — SignedIn, SignedOut, SessionLoading, Verified, Flag —
take over the page's own markup as DOM. Handing them children from React means
two owners for the same nodes. In an app that has React, read the session and
render the branch yourself.
Licence
MIT
