The package containing React components useful when processing Kontent.ai data to the site.
npm install @kontent-ai/react-componentsThe package containing React components useful when processing Kontent.ai's data to the site.
``sh`
npm install @kontent-ai/react-components
Components exports their typescript definitions so that you know what data format you need to provide via props and what data format expect from function prop callback arguments.
Rich text elements from Kontent.ai could be resolved to React components using html-react-parser (based on this article)
This package should make the usage easier. Basically by loading the rich text data and use these components to provide this data and resolver functions.
> More showcases could be found in RichTextElement.spec.tsx.
`tsx
import { createDeliveryClient, Elements } from '@kontent-ai/delivery-sdk';
import { isComponent, isLinkedItem, RichTextElement } from '@kontent-ai/react-components';
import { Element as DomHandlerElement } from 'domhandler';
// ...
const client = createDeliveryClient({
environmentId: '
});
const response = await client.item("
.toPromise();
// ...
resolvers={{
resolveLinkedItem: (linkedItem, { domElement, domToReact }) => {
if (isComponent(domElement)) {
return (
<>
{JSON.stringify(linkedItem, undefined, 2)};{JSON.stringify(linkedItem, undefined, 2)};}>
{domToReact(domElement.children)}
$3
If you want to resolve multiple levels of components and linked items in rich text, it is possible to use the component recursively and reuse the resolving logic.
There is an example when rich text can have
row components, and these can contains column components with html.`tsx
// resolving functionality
const resolveLinkedItemsRecursively: ResolveLinkedItemType = (
linkedItem,
_domNode
) => {
switch (linkedItem?.system.type) {
case "row":
return (
richTextElement={
linkedItem?.elements["columns"] as Elements.RichTextElement
}
// Recursively resolve items in the rich text
resolvers={{
resolveLinkedItem: resolveLinkedItemsRecursively,
}}
/>
);
case "column":
return (
richTextElement={
linkedItem?.elements["content"] as Elements.RichTextElement
}
resolvers={{
resolveLinkedItem: resolveLinkedItemsRecursively,
}}
/>
);
}
};// SO the top level rich text would define
richTextElement={
multiLevelComponentsRichTextItem.item.elements[
"content"
] as Elements.RichTextElement
}
resolvers={{
resolveLinkedItem: resolveLinkedItemsRecursively,
}}
/>;
`> ⚠ Recursive resolution could lead to infinite loops, if you have a circular dependency. To avoid that, you can store the codenames of already processed items and if you hit the same one during resolution, break the resolution chain - this could happen only if you use linked items, not components in rich text.
$3
By returning the react components in any of the resolvers functions, you stop traversing the DOM tree under the current DOM node (its children). If you just want to avoid that behavior, you can mutate the provided DOM node and return
undefined.In this showcase a simple html is being resolved and for
tags and all tags a proper class is being set without stopping and traversing.
` Lorem ipsum with bold texttsx`
...emptyRichText,
value: "
}}
resolvers={{
resolveDomNode: ({ domNode, domToReact }) => {
if (domNode instanceof DomHandlerElement) {
if (domNode.name === "strong") {
domNode.attribs.class = domNode.attribs.class
? domNode.attribs.class + " strongClass"
: "strongClass";
return undefined;
} else if (domNode.name === "p") {
domNode.attribs.class = domNode.attribs.class
? domNode.attribs.class + " pClass"
: "pClass";
return undefined;
}
}
},
}}
/>
The outcome is
`html``
Lorem ipsum with
bold text
If you have any feedback, feel free to submit an issue or open a PR!