-
-
Notifications
You must be signed in to change notification settings - Fork 757
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
serializeHtml
throws Invalid hook call
error
#2804
Comments
Is there any update? |
No ETA until consulting request. |
I'm having the same issue. |
Having the issue too |
@zbeyens Any solution? |
After thorough debugging over several hours, it was determined that the issue arose from the inclusion of the createBlockSelectionPlugin with specific options, notably:
The solution involved filtering the array of plugins to exclude the blockSelection plugin:
Subsequently, the modified array excludedSelectionPlugin was passed to the createPlateEditor function:
This adjustment successfully resolved the encountered issue. Hope you will figure out the original issue which was caused by 'createBlockSelectionPlugin'; |
@andshonia Thank you. Your solution works in my case. |
I have the same issue but the workaround is not working for me. It appears that other plugins might also have bug which is causing invalid hook call. |
Invalid hook call. Hooks can only be called inside of the body of a function component. |
I find out, that your solution is not working for me, and made some debugging. now I can See, that |
By filter out the |
for me filtering
Latest v34 |
I removed the p filtering now it works without it!!!! But i am facing another problem, i am desearilizing a html and showing it in the editor, but if there is any text, (p tag), the editor get reset if i type something |
By creating a temporary editor and replacing serializeHtml with htmlReact, this solution worked for me <Plate
editor={editor}
onChange={() => {
const tmp = createPlateEditor({
plugins: [HtmlReactPlugin],
})
const html= tmp.api.htmlReact.serialize({ nodes: editor.children })
console.log(html)
}}
>
<FixedToolbar>
<FixedToolbarButtons />
</FixedToolbar>
<Editor />
<FloatingToolbar>
<FloatingToolbarButtons />
</FloatingToolbar>
<CommentsPopover />
</Plate> |
This worked for me! Lifesaver took me 2 days and your comment saved me. |
You're omitting the components so this would serialize to default div and span without any styles. The workaround to above errors is to pass your own context-free components this way: const tmp = createPlateEditor({
plugins: [HtmlReactPlugin],
override: {
components: {
p: HtmlParagraphElement,
// ...
}
}
}) |
I solved it by blocking the BlockSelectionPlugin |
Doing like this doesn't it mean opting out the |
We'll work on read-only components compatible with this serializer, that will also be useful for read-only editors. |
Put editor.api.htmlReact.serialize({nodes:editor.children}) in a separate function. as it can't be use inside Plate's onChange handler. // PLATE COMPONENTS
import { Editor } from "@/components/plate-ui/Editor";
import { FixedToolbar } from "@/components/plate-ui/FixedToolbar";
import { FixedToolbarButtons } from "@/components/plate-ui/fixed-toolbar-buttons";
import { TooltipProvider } from "@/components/plate-ui/Tooltip";
import { useCreateEditor } from "@/hooks/useCreateEditor";
import { useEffect, useRef, useState } from "react";
import { Plate } from "@udecode/plate-common/react";
export const EditorComponent = () => {
const [content, setContent] = useState<any>("");
const [_html, setHTML] = useState<any>("");
const [isClicked, setIsClicked] = useState<boolean>(false);
const containerRef = useRef(null);
const editor = useCreateEditor();
useEffect(() => {
console.log("CONTENT", content);
}, [content, _html]);
const converToHtml = () => {
const html = editor.api.htmlReact.serialize({
nodes: content,
stripDataAttributes: false,
stripWhitespace: false,
// preserveClassNames: ["slate-h1", "slate-h2", "slate-h3"],
});
setHTML(html);
console.log("Serialized HTML:", html);
setIsClicked(true);
console.log("HTML", _html);
};
return (
<>
<Plate
editor={editor}
onChange={({ value }) => {
setContent(value);
}}
>
<FixedToolbar className="sticky">
<FixedToolbarButtons />
</FixedToolbar>
<TooltipProvider>
<Editor ref={containerRef} className="h-auto" />
</TooltipProvider>
</Plate>
<button
className="border bg-purple-900 text-white text-2xl rounded-md p-2"
onClick={converToHtml}
>
convert to HTML
</button>
{isClicked ? (
<div
className="w-full border border-black h-[100vh]"
dangerouslySetInnerHTML={{ __html: _html }}
/>
) : null}
</>
);
}; |
Could a kind soul give me some additional information on this I would like to revive the topic: I would like to render the HTML in relation to what was written, and if possible without a temporary editor (which is not, in my opinion, a viable solution). |
This requires some effort. We'll abstract this as soon as we can. |
Well, you can try to wrap up your editor component with Hoc. |
I'm doing it like this as well, but I get plain divs with none of the applied styles: <div>Playground</div><div class="slate-p">A rich-text editor with AI capabilities. Try the AI commands or use Cmd+J to open the AI menu.</div> const tmpEditor = createPlateEditor({
plugins: [HtmlReactPlugin],
override: {
components: editorComponents,
},
})
const html = tmpEditor.api.htmlReact.serialize({
nodes: editor.children,
convertNewLinesToHtmlBr: true,
stripWhitespace: false,
dndWrapper: (props) => (
<DndProvider backend={HTML5Backend} {...props} />
),
});
export const editorComponents = {
// [AIPlugin.key]: AILeaf,
[BlockquotePlugin.key]: BlockquoteElement,
[BoldPlugin.key]: withProps(PlateLeaf, { as: "strong" }),
[CodeBlockPlugin.key]: CodeBlockElement,
[CodeLinePlugin.key]: CodeLineElement,
[CodePlugin.key]: CodeLeaf,
[CodeSyntaxPlugin.key]: CodeSyntaxLeaf,
[ColumnItemPlugin.key]: ColumnElement,
[ColumnPlugin.key]: ColumnGroupElement,
[CommentsPlugin.key]: CommentLeaf,
[DatePlugin.key]: DateElement,
[EmojiInputPlugin.key]: EmojiInputElement,
[HEADING_KEYS.h1]: withProps(HeadingElement, { variant: "h1" }),
[HEADING_KEYS.h2]: withProps(HeadingElement, { variant: "h2" }),
[HEADING_KEYS.h3]: withProps(HeadingElement, { variant: "h3" }),
[HEADING_KEYS.h4]: withProps(HeadingElement, { variant: "h4" }),
[HEADING_KEYS.h5]: withProps(HeadingElement, { variant: "h5" }),
[HEADING_KEYS.h6]: withProps(HeadingElement, { variant: "h6" }),
[HighlightPlugin.key]: HighlightLeaf,
[HorizontalRulePlugin.key]: HrElement,
[ImagePlugin.key]: ImageElement,
[ItalicPlugin.key]: withProps(PlateLeaf, { as: "em" }),
[KbdPlugin.key]: KbdLeaf,
[LinkPlugin.key]: LinkElement,
[MediaEmbedPlugin.key]: MediaEmbedElement,
[MentionInputPlugin.key]: MentionInputElement,
[MentionPlugin.key]: MentionElement,
[ParagraphPlugin.key]: ParagraphElement,
[SlashInputPlugin.key]: SlashInputElement,
[StrikethroughPlugin.key]: withProps(PlateLeaf, { as: "s" }),
[SubscriptPlugin.key]: withProps(PlateLeaf, { as: "sub" }),
[SuperscriptPlugin.key]: withProps(PlateLeaf, { as: "sup" }),
[TableCellHeaderPlugin.key]: TableCellHeaderElement,
[TableCellPlugin.key]: TableCellElement,
[TablePlugin.key]: TableElement,
[TableRowPlugin.key]: TableRowElement,
[TocPlugin.key]: TocElement,
[TogglePlugin.key]: ToggleElement,
[UnderlinePlugin.key]: withProps(PlateLeaf, { as: "u" }),
}; |
You got a solution? I have same problem. |
U need to specify every className that your custom components uses. For example u have smth like this export const ParagraphElement = withRef<typeof PlateElement>(
({ children, className, ...props }, ref) => {
return (
<PlateElement
ref={ref}
className={cn("m-0 px-0 py-1", className)}
{...props}
>
{children}
</PlateElement>
);
},
); you need to specify every className in serializer const html = tmp.api.htmlReact.serialize({
nodes: editor.children,
stripDataAttributes: false,
stripWhitespace: false,
dndWrapper: props => <DndProvider backend={HTML5Backend} {...props} />,
preserveClassNames: [
"relative",
"m-0",
"px-0",
"py-1",
"slate-p",
"slate-selectable",
],
}); hope this helps |
we now have |
We are deprecating You can find a detailed guide here. And the complete example including export to HTML, Tailwind CSS, and Prism. |
Description
When calling
serializeHtml
(from@udecode/plate-serializer-html
), React throws an invalid hook error:Steps to Reproduce
I have a component,
CustomPlateEditor
. In this component, I have:My
editorRef
is passed down from a parent component, which contains the following code:When making any sort of change inside my Plate editor, I end up getting the invalid hook error, which I've narrowed down to only happening due to the
nodes: editorRef.current.children
part of the serializeHtml function. I've tried various other approaches including creating a temporary editor and passing in the editor value, but I get the same React hook error. I've checked that I don't have different versions of React running, so it seems to be an issue within@udecode/plate-serializer-html
Sandbox
I will make a code sandbox within a couple of days and update this issue.
Expected Behavior
I would expect that, with the given code I have in my app, making any change to the Plate rich text editor would result in a raw html string being set for my
editorHtmlValue
state value.Environment
[email protected]
[email protected]
@udecode/[email protected]
Funding
The text was updated successfully, but these errors were encountered: