Client-side context

Developer preview

This feature is in developer preview. Use with caution as it may change unexpectedly. For more information, contact us.

Developer Preview

This page documents the developer preview of the SDK, version 20.81.1-alpha.25.sha-f076f9b857.

Most Uniform components render on the server and do not use JavaScript in the browser. These tasks use the browser Context:

  • Read or update the quirks of the visitor
  • Read the scores of the visitor
  • Update the page when the Context changes

warning

Put "use client" at the top of the file of a component that uses useUniformContext, useQuirks, useScores or a browser API. This is a rule of React Server Components.

Keep client components small, and put them low in the component tree. "use client" makes the component and all its children client components. Then more JavaScript goes to the browser. For example, put only the button that updates a quirk in a client component, not the full page.

useUniformContext gives the Uniform Context instance in the browser:

"use client"; import { useUniformContext } from "@uniformdev/next-app-router/component"; export const QuirkButton = () => { const { context } = useUniformContext(); return ( <button disabled={!context} onClick={() => context?.update({ quirks: { country: "Canada" } })} > Set the country to Canada </button> ); };

note

context is undefined until the browser Context is ready. Always check for undefined.

useQuirks returns the quirks of the visitor. The component renders again when the quirks change:

"use client"; import { useQuirks } from "@uniformdev/next-app-router/component"; export const LocationBanner = () => { const quirks = useQuirks(); return <div>Country: {quirks?.country ?? "Unknown"}</div>; };

useScores returns the scores of the visitor. The component renders again when the scores change:

"use client"; import { useScores } from "@uniformdev/next-app-router/component"; export const InterestIndicator = () => { const scores = useScores(); return <div>Tech interest score: {scores?.tech ?? 0}</div>; };

A custom client context lets you add Context plugins, for example analytics, or change the dev tools. Install @uniformdev/context, then make the component:

components/CustomUniformClientContext.tsx

"use client"; import { type ContextPlugin, enableContextDevTools } from "@uniformdev/context"; import { type ClientContextComponent, createClientUniformContext, useInitUniformContext, } from "@uniformdev/next-app-router/component"; import { useRouter } from "next/navigation"; export const CustomUniformClientContext: ClientContextComponent = ({ manifest, disableDevTools, defaultConsent, experimentalQuirkSerialization, compositionMetadata, }) => { const router = useRouter(); useInitUniformContext(() => { const plugins: ContextPlugin[] = []; if (!disableDevTools) { plugins.push(enableContextDevTools({ onAfterMessageReceived: () => router.refresh() })); } return createClientUniformContext({ manifest, plugins, defaultConsent, experimental_quirksEnabled: experimentalQuirkSerialization, }); }, compositionMetadata); return null; };

Give it to UniformComposition (and to UniformPlayground, if you want it there too):

<UniformComposition code={code} resolveComponent={resolveComponent} clientContextComponent={CustomUniformClientContext} />

useInitUniformContext makes the Context one time in the browser. On each client-side navigation, it updates the Context with the new URL and the quirks from the middleware.