UNPKG

@contensis/canvas-react

Version:
174 lines (143 loc) 4.61 kB
# @contensis/canvas-react Render content curated in a Contensis canvas field in your React projects. ## Installation Install with your project's preferred package manager ```sh npm install --save @contensis/canvas-react ``` ```sh yarn add --save @contensis/canvas-react ``` ## Usage Render canvas content with React ```tsx import React, { useState } from 'react'; import ReactDOM from 'react-dom/client'; import { RenderContextProvider, Renderer } from '@contensis/canvas-react'; import * as CanvasData from './canvas-data'; // Our React App const App = () => { const [data] = useState(CanvasData.data); // Demo data return ( <div className="content"> <RenderContextProvider> <Renderer data={data} /> </RenderContextProvider> </div> ); }; const element = document.getElementById('root') as HTMLElement; ReactDOM.createRoot(element).render( <React.StrictMode> <App /> </React.StrictMode> ); ``` You can override the default rendering for content blocks by adding your own render components when creating the canvas renderer ```tsx import React, { useState } from 'react'; import ReactDOM from 'react-dom/client'; import { Block, Image, ImageBlock, RenderBlockProps, RenderContextProvider, Renderer, Table, TableBlock } from '@contensis/canvas-react'; import * as CanvasData from './canvas-data'; const MyImage = (props: RenderBlockProps<ImageBlock>) => { // Embelish the image markup if a caption is included const caption = props.block?.value?.caption; // Set a className for the image in all cases return !!caption ? ( <figure className="figure" style={{ display: 'block' }}> <Image {...props} className="figure-img img-fluid" /> <figcaption className="figure-caption text-end">{caption}</figcaption> </figure> ) : ( <Image {...props} className="img-fluid" /> ); }; const MyTable = (props: RenderBlockProps<TableBlock>) => { // Set CSS className on tables return <Table {...props} className="table table-striped" />; }; // Component wrapping a Renderer for simple usage const SimpleRenderer = ({ data }: { data: Block[] }) => { return ( <RenderContextProvider blocks={{ _image: MyImage, _table: MyTable }} > <Renderer data={data} /> </RenderContextProvider> ); }; // Our React App const App = () => { const [data] = useState(CanvasData.data); // Demo data return ( <div className="content"> <SimpleRenderer data={data} /> </div> ); }; const element = document.getElementById('root') as HTMLElement; ReactDOM.createRoot(element).render( <React.StrictMode> <App /> </React.StrictMode> ); ``` We can do the same for any Component fields present in the Canvas data ```tsx import React, { useState } from 'react'; import ReactDOM from 'react-dom/client'; import { Block, Image, RenderContextProvider, Renderer, Table } from '@contensis/canvas-react'; import * as CanvasData from './canvas-data'; type Book = { cover: string; name: string }; // Render a "book" component within the canvas data const MyBookComponent = (props: RenderBlockProps<ComponentBlock<Book>) => { const book = props.block?.value; if (!book) return null; return ( <div className="card mb-3"> <div className="row g-0"> <div className="col-md-8"> <div className="card-body"> <h5 className="card-title">{book.name}</h5> <p className="card-text">{book.name}</p> </div> </div> <div className="col-md-4"> <img src={book.cover} className="img-fluid rounded-start" /> </div> </div> </div> ); } // Component wrapping a customised Renderer for use in our app const SimpleRenderer = ({ data }: { data: Block[] }) => { return ( <RenderContextProvider components={{ book: MyBookComponent, }} > <Renderer data={data} /> </RenderContextProvider> ); }; // Our React App const App = () => { const [data] = useState(CanvasData.data); // Demo data return ( <div className="content"> <SimpleRenderer data={data} /> </div> ); }; const element = document.getElementById('root') as HTMLElement; ReactDOM.createRoot(element).render( <React.StrictMode> <App /> </React.StrictMode> ); ``` You try this out with the [React example project](https://github.com/contensis/canvas/tree/main/apps/react)