Handling dynamic datas inside Custom Formatting — Formatting Api
-
Hello Everyone,
I’m currently working on a custom “tooltip” formatting (for the RichText component), and I’m facing a problem which I would like to understand better.
The idea of the formatting is the following :
? 1 — The user selects some text
? 2 — The user click on the formatting button in the toolbar
? 3 — The toolbar button triggers a popover with a linkControl inside
? 4 — The user selects a post inside the link control (pre-existing definition stored in acf field, in a custom post type “vocabulaire”)
? 5 — When the user validates his choice on the linkControl,a onChange function is called.
? 6 — The onChange function fetches post Datas (acf field) from the post selected by the user (the object directly returned by the linkControl does not provide acf field)
? 7 — The format is applied with some of the fetched datas, though formatting attributes.
I guess the idea might get close to the native link formatting behaviour.
I managed to handle correctly the 5 first steps, but I’m stucked with handling asynchronous datas coming from the useSelect. I’m not a react or Gutenberg expert, and I’m not sure to understand how I should handle the asynchronous data coming from useSelect, or where to fetch datas from my acf field.
I’m facing invalid hook call error when using useSelect inside the onChange function, or regularly having a too many re-renders error when trying different approaches.
Here is my code :import { __ } from "@wordpress/i18n"; import { registerFormatType, toggleFormat, applyFormat, getActiveFormats } from "@wordpress/rich-text"; import { BlockControls, __experimentalLinkControl as LinkControl } from "@wordpress/block-editor"; import { Popover, ToolbarGroup, ToolbarButton } from "@wordpress/components"; import { trash } from "@wordpress/icons"; import { useState } from "@wordpress/element"; import { useSelect } from "@wordpress/data"; // pour les querry const formatName = "homegrade-format/tooltip"; const Edit = (props) => { const { isActive, value, onChange } = props; const [isPopoverOpen, setIsPopoverOpen] = useState(false); const [popoverText, setPopoverText] = useState(""); const activeFormat = getActiveFormats(props.value).filter((format) => format.type === formatName)[0]; // #OPTION 2 — GET POST DATAS HERE AND RE-APPLY FORMAT WITH FETCHED DATAS WHEN COMPONENT IS RELOADED // PROBLEM -> how to access postDatas from here ? const post = useSelect((select) => { if (activeFormat && activeFormat.attributes.definitionId) { return select("core").getEntityRecord("postType", "vocabulaire", 940); } }); if (post) { onChange( applyFormat(value, { type: formatName, attributes: { dataTooltip: post.acf.definition, // }, }) ); } // END OF OPTION 2 function removeFormat() { setIsPopoverOpen(false); onChange( toggleFormat(value, { type: formatName, }) ); } function setFormat(postDatas) { // -> postDatas returns something like this (without acf field in post content) -> {url: 'https://homegrade.local/fiche/eaux-dinfiltration/', id: 940, title: 'Eaux d’infiltration', type: 'vocabulaire', kind: 'post-type'} // #OPTION 1 — GET POST DATAS HERE AND PASS IT DIRECTLY TO THE ATTRIBUTES // PROBLEM -> I get this error https://legacy.reactjs.org/docs/error-decoder.html/?invariant=321 const post = useSelect((select) => { if (activeFormat && activeFormat.attributes.definitionId) { return select("core").getEntityRecord("postType", "vocabulaire", postDatas.id); } }); setIsPopoverOpen(false); onChange( applyFormat(value, { type: formatName, attributes: { definitionId: postDatas.id.toString(), dataTooltip: post.whateverProperty, }, }) ); } return ( <> <BlockControls> {isPopoverOpen && ( <Popover onClose={() => setIsPopoverOpen(false)} className='popover_tooltip_field'> <LinkControl suggestionsQuery={{ type: "post", subtype: "vocabulaire", }} onChange={(postDatas) => setFormat(postDatas)} /> </Popover> )} <ToolbarGroup> <ToolbarButton isActive={isActive} icon={!isActive ? "admin-comments" : trash} label={!isActive ? "Add tooltip" : "Delete tooltip"} onClick={() => { !isActive ? setIsPopoverOpen(true) : removeFormat(); }} /> </ToolbarGroup> </BlockControls> </> ); }; registerFormatType(formatName, { title: __("Tooltip", "homegrade-format"), tagName: "span", attributes: { definitionId: "data-definition-id", dataTooltip: "data-tooltip", }, className: "tooltip-word", edit: Edit, });
How can I properly get datas with useSelect and pass them properly to my formatting attributes ?
I’m pretty sure I’m getting some concepts wrong and would love to understand them better.
- The topic ‘Handling dynamic datas inside Custom Formatting — Formatting Api’ is closed to new replies.