Extension Factories
Extension API
Extension Points

Render element as React

The renderElementAsReact function is a utility provided to render custom content using React with the Client-side Extensions API.

It handles the mount/unmount cycles and rendering/unmounting the provided component for you. Also, it's recommended to use it since optimizations to React rendering content will be applied here in the future.

Signature

1
2
type renderElementAsReact = <PropsT>(
    renderApi: PanelAPI | ModalApi,
    RenderElement: ComponentType<PropsT>,
    additionalProps?: PropsT,
) => void;

Arguments

NameTypeDescription
renderApi*PanelApi | ModalApiThe API object received in the onAction method should be provided as the argument. Only works for Panels and Modals.
RenderElement*ComponentType

A React component.

Don't use JSX syntax here instead reference the React component e.g. MyComponent but not <MyComponent />

additionalPropsobject An optional object with additional props that will be bind to the component once mounted.

* required

Usage notes

1. Rendering a React component as content of a panel

my-extension.ts

1
2
import { PanelExtension } from '@atlassian/clientside-extensions';
import { renderElementAsReact } from '@atlassian/clientside-extensions-components';

import PanelContent from './panel-content';

/**
 * @clientside-extension
 * @extension-point reff.plugins-example-location
 */
export default PanelExtension.factory(() => {
    return {
        label: `React panel`,
        onAction(panelApi) {
            renderElementAsReact(panelApi, PanelContent);
        },
    };
});

panel-content.ts

1
2
const PanelContent = () => {
    return <p>Hello World!</p>;
};

export default PanelContent;

2. Rendering a React component as content of an asynchronous panel with additional props

my-extension.ts

1
2
import { AsyncPanelExtension } from '@atlassian/clientside-extensions';
import { MyContext } from './types';

const moduleLoader = () => import('./my-panel');

/**
 * @clientside-extension
 * @extension-point reff.plugins-example-location
 */
export default AsyncPanelExtension.factory<MyContext>(() => {
    return {
        label: `React async panel`,
        onAction: moduleLoader,
    };
});

my-panel.ts

1
2
import { PanelExtension, renderElementAsReact } from '@atlassian/clientside-extensions-components';
import MyPanelContent, { MyPanelContentProps } from './my-panel-content';
import { MyContext } from './types';

export default function initAsyncPanel(
  panelApi: PanelExtension.Api,
  context: MyContext
) {
    renderElementAsReact<MyPanelContentProps>(panelApi, MyPanelContent, { context });
}

my-panel-content.ts

1
2
import React from 'react';
import { MyContext } from './types';

export type MyPanelContentProps = {
    context: MyContext;
};

const MyPanelContent: React.FC<MyPanelContentProps> = ({ context }) => {
    return <p>Hello ${context.label}!</p>;
};

export default MyPanelContent;

types.ts

1
2
export type MyContext {
    label: string;
}

3. Rendering a React component as content of a modal with additional props

1
2
import { ModalExtension } from '@atlassian/clientside-extensions';
import { renderElementAsReact } from '@atlassian/clientside-extensions-components';
import React from 'react';

type MyContext = {
    /*...*/
}

type ReactComponentProps = {
    context: MyContext;
    modalAPI: ModalExtension.Api;
};

const ReactComponent: React.FC<ReactComponentProps> = ({ context, modalAPI }) => {
    modalAPI.setTitle('An awesome modal with react');

    modalAPI.onClose(() => {
        /*...*/
    });

    modalAPI.setActions([
        /*...*/
    ]);

    return ( /*..Your custom modal content goes here..*/);
};

/**
 * @clientside-extension
 * @extension-point reff.plugins-example-location
 */
export default ModalExtension.factory<MyContext>((pluginApi, context) => {
    return {
        label: `Modal with react content`,
        onAction(modalAPI) {
            renderElementAsReact<ReactComponentProps>(
              modalAPI,
              ReactComponent,
              { modalAPI, context }
            );
        },
    };
});

Rate this page: