Skip to content

Latest commit

 

History

History
202 lines (158 loc) · 4.32 KB

README.md

File metadata and controls

202 lines (158 loc) · 4.32 KB

Cafe CMS - React Client

Cafe is here to supersede clunky content management systems.

About Cafe CMS

Authored by the Trioxis team. CafeCMS:

  • allows developers to build beautiful progressive web apps
  • whilst enabling non-developers to edit copy and content

The admin panel is under development, for now, see the api at api.cms.cafe/graphiql to add content.

About this React Client

The React Cafe Client simplifies usage of Cafe within a react environment. It provides a simple higher order component to inject content.

Usage

Use npm or yarn:

npm install @trioxis/react-cafe-cms
yarn add @trioxis/react-cafe-cms

Setup and basic usage

Setup the root provider component at the top level of your app:

import React from 'react';
import {CMSProvider} from '@trioxis/react-cafe-cms';

import MyPage from './MyPage';

function MyApp () {
  return (
    <CMSProvider website='trioxis.com'>
      <MyPage />
    </CMSProvider>
  );
}

export default MyApp;

Then inject a content prop into your components using the injectContent higher order component:

// ./MyPage
import React from 'react';
import {injectContent} from '@trioxis/react-cafe-cms';

function MyPage (props) {
  const {content} = props
  return (
    <div>
      {content.helloWorld}
    </div>
  );
}

export default injectContent('helloWorld')(MyPage);

The content prop is an object with keys corresponding to each requested slug.

You can provide injectContent with any number of arguments for each slug you want to retrieve

// ./MyPage
import React from 'react';
import {injectContent} from '@trioxis/react-cafe-cms';

function MyPage (props) {
  const {content} = props
  return (
    <div>
      <p>{content.helloWorld}</p>
      <p>{content.seasonalOffer}</p>
    </div>
  );
}

export default injectContent('helloWorld', 'seasonalOffer')(MyPage);

You can provide injectContent with a single function that recieves props and returns an array of slugs to retrieve. Use this to dynamically figure out the slugs based on props.

import React from 'react';
import {injectContent} from '@trioxis/react-cafe-cms';

function offerBox (props) {
  const {type, content} = props;
  return (
    <div>
      <h1>{content.offerTitle}</h1>
      <p>{content[type]}</p>
    </div>
  )
}

const MyOffer = injectContent(
  props => ['offerTitle', props.type]
)(offerBox);

function MyPage (props) {
  return (
    <MyOffer type="seasonal" />
  );
}

export default MyPage;

Showing loading content

Keys on content are only defined once a response is received from the API. You can use the __loading key to determine if a response is still in flight.

// ./MyPage
import React from 'react';
import {compose} from 'recompose';
import {injectStyles} from 'react-jss';
import {injectContent} from '@trioxis/react-cafe-cms';

const styles = {
  wireframe: {
    backgroundColor: '#dddddd',
    width: '200px',
    height: '50px'
  }
}
function MyPage (props) {
  const {content, classes} = props
  return (
    <div className={content.__loading ? classes.wireframe : null}>
      {content.helloWorld}
    </div>
  );
}

export default compose(
  injectContent('helloWorld'),
  injectStyles(styles)
)(MyPage);

How to avoid many round trips

To request all content in a single round trip, we must statically pass up the required content for each component.

// ./MyContent
import React from 'react';
import {injectContent} from '@trioxis/react-cafe-cms';
import {compose, setStatic} from 'recompose';

const content = ['helloWorld']

function MyContent (props) {
  const {content} = props
  return (
    <div>
      {content.helloWorld}
    </div>
  );
}

export default compose(
  setStatic('content', content),
  injectContent(...content)
)(MyContent);
// ./MoreContent
import React from 'react';
import {compose} from 'recompose';
import {injectContent} from '@trioxis/react-cafe-cms';
import MyContent from './MyContent';

const content = ['suchWow']

function MoreContent (props) {
  const {content} = props
  return (
    <div>
      {content.suchWow}
      <MyContent />
    </div>
  );
}

export default compose(
  injectContent(...content, ...MyContent.content)
)(MoreContent);

Development

To work on the client itself, see the development readme