@dotcms/react
Version:
Official React Components library to render a dotCMS page.
136 lines (133 loc) • 4.34 kB
JavaScript
import { useState, useEffect } from 'react';
import { UVEEventType } from '@dotcms/types';
import { getUVEState, initUVE, updateNavigation, createUVESubscription } from '@dotcms/uve';
import { registerStyleEditorSchemas } from '@dotcms/uve/internal';
/**
* Custom hook to manage the editable state of a DotCMS page.
*
* This hook initializes the Universal Visual Editor (UVE) and subscribes to content changes.
* It updates the editable page state when content changes are detected in the UVE,
* ensuring your React components always display the latest content when editing in DotCMS.
*
* @example
* ```ts
* // Import the hook and the client
* import { useEditableDotCMSPage } from '@dotcms/react';
* import { createDotCMSClient } from '@dotcms/client';
*
* // Create the client
* const client = createDotCMSClient({
* dotcmsURL: 'https://your-dotcms-instance.com',
* authToken: 'your-auth-token'
* });
*
* // Get the page
* const page = await client.page.get('/', {
* languageId: '1',
* });
*
* // Use the hook to get an editable version of the page
* const editablePage = useEditableDotCMSPage(page);
*
* // Then use the page data in your component
* return (
* <div>
* <h1>{editablePage.page.title}</h1>
* <div dangerouslySetInnerHTML={{ __html: editablePage.page.body }} />
* </div>
* );
* ```
*
* @example
* ```ts
* // Import the hook and the client
* import { useEditableDotCMSPage } from '@dotcms/react';
* import { createDotCMSClient } from '@dotcms/client';
*
* // Create the client
* const client = createDotCMSClient({
* dotcmsURL: 'https://your-dotcms-instance.com',
* authToken: 'your-auth-token'
* });
*
* // Get the page with GraphQL content
* const page = await client.page.get('/', {
* languageId: '1',
* graphql: {
* content: {
* products: `ProductCollection(query: "+title:snow", limit: 10, offset: 0, sortBy: "score") {
* title
* urlMap
* category {
* name
* inode
* }
* retailPrice
* image {
* versionPath
* }
* }`
* }
* }
* });
*
* // Use the hook to get an editable version of the page and its content
* const editablePage = useEditableDotCMSPage(page);
*
* // Access both page data and GraphQL content
* const { page: pageData, content } = editablePage;
*
* // Use the products from GraphQL content
* return (
* <div>
* <h1>{pageData.title}</h1>
* <ProductList products={content.products} />
* </div>
* );
* ```
* @param {DotCMSPageResponse} pageResponse - The initial editable page data from client.page.get().
*
* @returns {DotCMSPageResponse} The updated editable page state that reflects any changes made in the UVE.
* The structure includes page data and any GraphQL content that was requested.
*/
const useEditableDotCMSPage = pageResponse => {
const [updatedPageResponse, setUpdatedPageResponse] = useState(pageResponse);
useEffect(() => {
var _pageResponse$pageAss, _pageResponse$styleEd;
if (!getUVEState()) {
return;
}
if (!pageResponse) {
console.warn('[useEditableDotCMSPage]: No DotCMSPageResponse provided');
return;
}
const pageURI = pageResponse == null || (_pageResponse$pageAss = pageResponse.pageAsset) == null || (_pageResponse$pageAss = _pageResponse$pageAss.page) == null ? void 0 : _pageResponse$pageAss.pageURI;
const {
destroyUVESubscriptions
} = initUVE(pageResponse);
// Update the navigation to the pageURI, when we have a pageURI
// Sometimes the page is null due to permissions, so we don't want to update the navigation
// And wait for the UVE to resolve the page
if (pageURI) {
updateNavigation(pageURI);
}
if ((_pageResponse$styleEd = pageResponse.styleEditorSchemas) != null && _pageResponse$styleEd.length) {
registerStyleEditorSchemas(pageResponse.styleEditorSchemas);
}
return () => {
destroyUVESubscriptions();
};
}, [pageResponse]);
useEffect(() => {
const {
unsubscribe
} = createUVESubscription(UVEEventType.CONTENT_CHANGES, payload => {
setUpdatedPageResponse(payload);
});
return () => {
unsubscribe();
};
}, []);
return updatedPageResponse;
};
export { useEditableDotCMSPage };