Using React Components with Scrivito’s Model Classes

Assigning a component to an object or widget class

As mentioned in the Introduction to Scrivito, CMS content is rendered in the browser by React components.

When rendering CMS objects or widgets, Scrivito needs to know which component to use for which model class. For assigning a component to an object or widget class, Scrivito.provideComponent is available. For example, assuming that there is a HeadlineWidget class that has a title attribute, you can have Scrivito render instances of this widget class by providing a suitable functional component:

Copy
Scrivito.provideComponent('HeadlineWidget', widget =>   
  <Scrivito.ContentTag tag="h1" content={ widget } attribute="title" />
);

You could also provide a class component instead. However, this is only recommended when using state (and in this case, it’s required):

Copy
class Headline extends React.Component {
  constructor(props) {
    super(props);
    this.state = { cssClass: 'bg-warning' };
  }

  handleEvent() {
    // Handle event that changes state
  }

  render() {
    return (
      <div className={ this.state.cssClass } onClick={ () => this.handleEvent() }>
        <Scrivito.ContentTag 
          tag="h1"
          content={ this.props.widget }
          attribute="title"
        />
      </div>
    );
  }
}

Scrivito.provideComponent('HeadlineWidget', Headline);

The provided component is connected to Scrivito, meaning that it automatically loads the required data from the Scrivito backend and automatically updates when new data becomes available.

Connecting stand-alone components to Scrivito

There are components that are independent of a specific model class and thus cannot be assigned to any of them. Such components render layout elements like navigations or notification boxes and should be integrated with Scrivito as well, so that their data is automatically loaded and updated. In order to achieve this, you can connect such a component to Scrivito using Scrivito.connect:

Copy
// 3rd-party library for formatting file size
import filesize from 'filesize';

function FileSizeBox(obj) {
  return (
    <div className="noticeBox fileSize">     
      { filesize(obj.contentLength()) }
    </div> 
  );
}

// Connect the component to Scrivito
export default Scrivito.connect(FileSizeBox);

CMS object and widget data is loaded asynchronously from Scrivito’s backend. Scrivito.connect frees you from having to handle pending data. It also ensures that a component is rerendered after the data has been loaded or changed. 

However, when accessing CMS data outside of rendering, for example inside an event handler such as onClick, you require Scrivito.load: It allows you to work consistently with the data loaded in the background.

In a nutshell...

When writing a component for a CMS model class (representing a page, resource, or widget type) use Scrivito.provideComponent and pass a functional component to it, unless you need to handle state. In this case create a React.Component class and pass it to Scrivito.provideComponent.

With components not intended for a CMS model class (see the GoogleAnalytics component as an example), always create a React.Component class and connect it to Scrivito using Scrivito.connect.