Wondering what’s next for npm?Check out our public roadmap! »

    @bloomreach/react-sdk
    TypeScript icon, indicating that this package has built-in type declarations

    14.6.0 • Public • Published

    Bloomreach React SDK

    NPM License

    Bloomreach React SDK provides simplified headless integration with Bloomreach Experience Manager for React-based applications. This library interacts with the Page Model API and Bloomreach SPA SDK and exposes a simplified declarative React interface over the Page Model.

    What is Bloomreach Experience Manager?

    Bloomreach Experience Manager (brXM) is an open and flexible CMS designed for developers and marketers. As the original headless CMS, brXM allows developers to build quickly and integrate with the systems. While it’s built for speed, it also provides top-notch personalization and channel management capabilities for marketers to drive results.

    Features

    Get Started

    Installation

    To get the SDK into your project with NPM:

    npm install @bloomreach/react-sdk

    And with Yarn:

    yarn add @bloomreach/react-sdk

    Usage

    The following code snippet renders a simple page with a Banner component.

    import React from 'react';
    import axios from 'axios';
    import { BrComponent, BrPage, BrPageContext, BrProps } from '@bloomreach/react-sdk';
    
    function Banner({ component }: BrProps) {
      return <div>Banner: {component.getName()}</div>;
    }
    
    export default function App() {
      const config = { /* ... */ };
    
      return (
        <BrPage configuration={config} mapping={{ Banner }}>
          <header>
            <BrPageContext.Consumer>
              { page => <Link to={page.getUrl('/')} />Home</Link> }
            </BrPageContext.Consumer>
            <BrComponent path="menu"><Menu /></BrComponent>
          </header>
          <section>
            <BrComponent path="main" />
          </section>
          <BrComponent path="footer">
            <footer><BrComponent /></footer>
          </BrComponent>
        </BrPage>
      );
    }

    Configuration

    The BrPage component supports several options you may use to customize page initialization. These options will be passed to the initialize function from @bloomreach/spa-sdk. See here for the full configuration documentation.

    Mapping

    The BrPage component provides a way to link React components with the brXM ones. It requires to pass the mapping property that maps the component type with its representation.

    • The Container Items can be mapped by their labels.

      import NewsList from './components/NewsList';
      
      return <BrPage mapping={{ 'News List': NewsList }} />;
    • The Containers can be only mapped by their type, so you need to use constants from @bloomreach/spa-sdk. By default, the React SDK provides an implementation for all the container types as it's defined in the documentation.

      import { TYPE_CONTAINER_INLINE } from '@bloomreach/spa-sdk';
      import MyInlineContainer from './components/MyInlineContainer';
      
      return <BrPage mapping={{ [TYPE_CONTAINER_INLINE]: MyInlineContainer }} />;

      From within the Container component, the Container Items can be accessed via the children property. This can be used to reorder or wrap child elements.

      export default function MyInlineContainer() {
        return (
          <div>
            {React.Children.map(props.children, child => (
              <span className="float-left">
                {child}
              </span>
            ))}
          </div>
        );
      }
    • The Components can be mapped by their names. It is useful for a menu component mapping.

      import Menu from './components/Menu';
      
      return <BrPage mapping={{ menu: Menu }} />;
    • By default, container items that are not mapped will be rendered as a warning text. There is an option to override the fallback.

      import { TYPE_CONTAINER_ITEM_UNDEFINED } from '@bloomreach/spa-sdk';
      import Fallback from './components/Fallback';
      
      return <BrPage mapping={{ [TYPE_CONTAINER_ITEM_UNDEFINED]: Fallback }} />;

    Inline Mapping

    There is also another way to render a component. In case you need to show a static component or a component from the abstract page, you can use inline component mapping.

    return <BrComponent path="menu"><Menu /></BrComponent>

    It is also possible to point where the component's children are going to be placed.

    return (
      <BrComponent path="footer">
        <footer><BrComponent /></footer>
      </BrComponent>
    );

    The component data in case of inline mapping can be accessed via the BrComponentContext.

    return (
      <BrComponentContext.Consumer>
        {component => (
          <BrComponent path="footer">
            <footer>
              &copy; {component.getName()}
              <BrComponent />
            </footer>
          </BrComponent>
        )}
      </BrComponentContext.Consumer>
    );

    Or by using React Hooks.

    import { BrComponentContext } from '@bloomreach/react-sdk';
    
    export default function Menu() {
      const component = React.useContext(BrComponentContext);
    
      return <ul>{component.getName()}</ul>;
    }

    Buttons

    • Manage menu button can be placed inside a menu component using BrManageMenuButton component.
      import React from 'react';
      import { Menu, Reference } from '@bloomreach/spa-sdk';
      import { BrComponentContext, BrManageMenuButton, BrPageContext } from '@bloomreach/react-sdk';
      
      interface MenuModels {
        menu: Reference;
      }
      
      export default function MenuComponent() {
        const component = React.useContext(BrComponentContext);
        const page = React.useContext(BrPageContext);
        const menuRef = component?.getModels<MenuModels>().menu;
        const menu = menuRef && page?.getContent<Menu>(menuRef);
      
        if (!menu) {
          return null;
        }
      
        return (
          <ul className={page?.isPreview() ? 'has-edit-button' : ''}>
            {/* ... */}
      
            <BrManageMenuButton menu={menu} />
          </ul>
        );
      }
    • Manage content button can be placed inside a component using BrManageContentButton component with non-empty content property.
      import React from 'react';
      import { Document, Reference } from '@bloomreach/spa-sdk';
      import { BrManageContentButton, BrProps } from '@bloomreach/react-sdk';
      
      interface BannerModels {
        document: Reference;
      }
      
      export default function Banner({ component, page }: BrProps) {
        const { document: documentRef } = component.getModels<BannerModels>();
        const document = documentRef && page.getContent<Document>(documentRef);
      
        return (
          <div className={page.isPreview() ? 'has-edit-button' : ''}>
            {/* ... */}
      
            <BrManageContentButton
              content={document}
              documentTemplateQuery="new-banner-document"
              folderTemplateQuery="new-banner-folder"
              parameter="document"
              root="banners"
              relative
            />
          </div>
        );
      }
    • Add new content button can be placed inside a component using BrManageContentButton directive but without passing a content entity.
      import React from 'react';
      import { BrManageContentButton, BrProps } from '@bloomreach/react-sdk';
      
      export default function News({ component, page }: BrProps) {
        // ...
      
        return (
          <div className={page.isPreview() ? 'has-edit-button' : ''}>
            {/* ... */}
      
            <BrManageContentButton
              documentTemplateQuery="new-news-document"
              folderTemplateQuery="new-news-folder"
              root="news"
            />
          </div>
        );
      }

    React Native

    The SDK is fully compatible with React Native framework, but there are some of the best practices.

    • It is impossible to use <div> elements in React Native, and it is recommended to use the hst.nomarkup container type in the backend configuration.

    • If there is a need to support other container types, those types should be overridden explicitly in the mapping. The default implementation is using HTML entities as described in the documentation.

      import React from 'react';
      import { View } from 'react-native';
      import { TYPE_CONTAINER_BOX } from '@bloomreach/spa-sdk';
      
      function MyBoxContainer() {
        return (
          <View>
            {React.Children.map(props.children, child => (
              <View>
                {child}
              </View>
            ))}
          </View>
        );
      }
      
      export default function App() {
        return <BrPage mapping={{ [TYPE_CONTAINER_BOX]: MyBoxContainer }} />;
      }
    • The fallback mapping should be overridden to prevent errors on production when a new component type pops up on the backend since the default implementation is returning a plain text node.

      import React from 'react';
      import { Text } from 'react-native';
      import { TYPE_CONTAINER_ITEM_UNDEFINED } from '@bloomreach/spa-sdk';
      
      function Fallback({ component, page }) {
        return page.isPreview() && <Text>Component "{component.getType()}" is not defined.</Text>;
      }
      
      export default function App() {
        return <BrPage mapping={{ [TYPE_CONTAINER_ITEM_UNDEFINED]: Fallback }} />;
      }
    • For integration with the Relevance Module, the visitor identifier storing and passing should be handled on the application side. There is the visitor option in the configuration that enables a setup without using cookies.

      import React, { useEffect, useMemo, useRef } from 'react';
      import { read, write } from './storage';
      
      export default function App() {
        const ref = useRef(null);
        const configuration = {
          /* ... */
          visitor: read('visitor'),
        };
      
        const visitor = ref.current
          && ref.current.state.page
          && ref.current.state.page.getVisitor();
      
        useEffect(() => void visitor && write('visitor', visitor), [visitor && visitor.id]);
      
        return <BrPage ref={ref} configuration={configuration} />;
      }

    Reference

    The React SDK is using Bloomreach SPA SDK to interact with the brXM. The complete reference of the exposed JavaScript objects can be found here.

    BrPage

    This is the entry point to the page model. This component requests and initializes the page model, and then renders the page root component with React children passed to this component. The component also sets the page object into BrPageContext.

    Property Required Description
    configuration yes The configuration of the SPA SDK.
    mapping yes The brXM and React components mapping.
    page no Preinitialized page instance or prefetched page model. Mostly that should be used to transfer state from the server-side to the client-side.

    BrComponent

    This component points to where children or some component should be placed. BrComponent can be used inside BrPage or mapped components only. If React children are passed, then they will be rendered as-are. Otherwise, it will try to render all children components recursively.

    Property Required Description
    path no The path to a component. The path is defined as a slash-separated components name chain relative to the current component (e.g. main/container). If it is omitted, all the children will be rendered.

    BrManageContentButton

    This component places a button on the page that opens the linked content in the document editor or opens a document editor to create a new one. The button will only be shown in preview mode.

    Property Required Description
    content no The content entity to open for editing.
    documentTemplateQuery no Template query to use for creating new documents.
    folderTemplateQuery no Template query to use in case folders specified by path do not yet exist and must be created.
    path no Initial location of a new document, relative to the root.
    parameter no Name of the component parameter in which the document path is stored.
    relative no Flag indicating that the picked value should be stored as a relative path.
    root no Path to the root folder of selectable document locations.

    BrManageMenuButton

    This component places a button on the page that opens the linked menu in the menu editor. The button will only be shown in preview mode.

    Property Required Description
    menu yes The related menu model.

    BrComponentContext

    The React Context holding the current brXM Component.

    BrPageContext

    The React Context holding the current brXM Page.

    Links

    FAQ

    License

    Published under Apache 2.0 license.

    Install

    npm i @bloomreach/react-sdk

    DownloadsWeekly Downloads

    2,675

    Version

    14.6.0

    License

    Apache-2.0

    Unpacked Size

    64.6 kB

    Total Files

    7

    Last publish

    Collaborators

    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar
    • avatar