Interactive client components
Developer preview
Goal: add a component that reacts to the visitor, for example a button that opens a panel. Send as little JavaScript to the browser as possible.
Prerequisites#
- A Next.js app with the SDK. Refer to Next.js App Router SDK.
- For the rich text example, the
@uniformdev/richtextpackage at the same version as the SDK.
Choose a pattern#
| Pattern | Use it when |
|---|---|
| A server component with a client child (recommended) | Only a small part of the component is interactive. You want visual editing for the text. |
| A client component in the component map | The full component is interactive, and it is small. |
Pattern 1: A server component with a client child#
The component in the component map stays a server component. It reads the parameters, and gives plain values to a small client component.
Step 1: Make the client component#
components/disclosure.tsx
The client component knows nothing about Uniform. It gets a boolean and two React nodes.
Step 2: Make the server component#
components/faq-item.tsx
Register FaqItem in components/resolveComponent.tsx.
FaqItem makes the UniformText and UniformRichText elements on the server. It gives them to Disclosure as props. Thus authors can still edit the text in Canvas. In Canvas, context.isContextualEditing is true, so the panel is open and the author can see the answer.
Pattern 2: A client component in the component map#
You can also put "use client" in the file of a registered component:
components/promo-code.tsx
Register it in the component map as usual. components/resolveComponent.tsx stays a server file:
components/resolveComponent.tsx
The serialization rule#
The SDK renders each component on the server. For a client component, React must serialize the props and send them to the browser. Props of a client component must be serializable. For example, plain objects, arrays, strings, numbers, booleans, null and React elements are serializable. Functions are not serializable.
ComponentProps obeys this rule:
| Prop | Contents |
|---|---|
type, variant | Strings |
parameters | The parameter data from Uniform, plus parameterId |
slots | For each slot: its name, and for each item its _id, its variant data and the rendered child as a React element |
component | IDs, the slot name and the slot index |
context | The composition ID and type, the state, isContextualEditing, matchedRoute, dynamicInputs and pageState |
The SDK also renders its own client components with these props, for example the component for personalizations.
warning
The browser gets all props of a client component, also the parameters that it does not use. Do not keep secret values in parameters of a client component. A server component with a client child (pattern 1) sends only the values that you give to the child.
Read the quirks and scores of the visitor#
useQuirks and useScores give the data of the visitor in a client component. The component renders again when the data changes:
components/visitor-greeting.tsx
On the server, useQuirks returns an empty object, and useScores returns undefined. Thus the server HTML always shows "Welcome.". When the browser Context is ready, the component renders again with the data of the visitor. Show a neutral default in the server HTML.
The vc-country quirk comes from the Vercel geolocation headers. Refer to Personalization and A/B tests.
tip
To show different content to different visitors, use a personalization in Uniform. The SDK renders the variants for you. Use the hooks only for small changes that do not need a personalization.
Update the Context#
useUniformContext gives the browser Context. Call context.update to change the data of the visitor. Personalizations on the page then select their variants again.
Set a quirk#
components/member-button.tsx
Make the quirk member in Uniform, so that personalization criteria can use it.
Add an enrichment score#
The server component reads the enrichment from its parameters. It gives the values as strings to the client button:
components/interest-button.tsx
components/interest-card.tsx
cat is the public ID of an enrichment category in Uniform. key is the public ID of a value in this category. str is the score to add.
Notes#
contextcan beundefined:useUniformContextreturnsundefineduntil the browser Context is ready. The examples disable the button until then.- Keep client components small:
"use client"makes the component and all components that it imports client components. Put only the interactive part in a client component. Refer to Client-side context. - Enrichment tags on components: if an author adds enrichment tags to a component in Canvas, the SDK updates the scores for you. You do not need code for this.