Component substitution in the Headless API

(See also component substitution in codegen.)

The componentProps API lets you customize any instance of a component, but when you are adding state or behavior (such as via hooks), you usually want this to be associated with the component itself (across all instances).

Besides attaching behavior, you may also want to altogether replace any component with an existing code component.

In these scenarios, you can tell Plasmic that wherever it encounters an instance of some Plasmic component, render instead a different React component of your choosing. This can be a wrapper that contains state/behavior, or it can be an entirely different component (don’t render the Plasmic design at all).

For example, maybe you have a EmailSubscribeForm component, and you want to add behavior to the form so your users can actually edit and submit that form. You want this behavior to be anywhere you’re using an EmailSubscribeForm in your designs.

First, you should create a wrapper component that performs all the instrumentation you want:

// MyEmailSubscribeForm.tsx
export function MyEmailSubscribeForm(props) {
const [email, setEmail] = React.useState("");
const isInvalidEmail = checkEmailValid(email);
return (
// Ask Plasmic to use the original, Plasmic-generated
// EmailSubscribeForm component
root: {
as: "form",
props: {
// add an onSubmit handler to the root form element
onSubmit: () => ...
input: {
// Control the input element value with React state
props: {
value: email,
onChange: (e) => setEmail(
// Activate a "isInvalid" variant based on whether the typed email is
// valid or not
isInvalid: isValidEmail

The above is a component that uses PlasmicComponent to render EmailSubscribeForm as it is designed in Plasmic, but with the above overrides for form submission, input changes, and variant activation.

Next, you need to tell Plasmic to use your special MyEmailSubscribeForm every where EmailSubscribeForm is used in your designs:

import { MyEmailSubscribeForm } from './components/MyEmailSubscribeForm';
PLASMIC.substituteComponent(MyEmailSubscribeForm, 'EmailSubscribeForm');

This tells Plasmic that anywhere we see EmailSubscribeForm, we should substitute in our special instrumented version instead. The only exception is inside MyEmailSubscribeForm.tsx itself, where, where we want to use the original generated EmailSubscribeForm component (hence the forceOriginal flag).

Was this page helpful?

Have feedback on this page? Let us know on our forum.