question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

@contentful/field-editor-rich-text re-rendering problem

See original GitHub issue

Hi all, I am using @contentful/field-editor-rich-text in a contentful app, version 2.1.0 and I have some problems with rerendering. Basically I am rendering a set of tabs and each tab has an instance of @contentful/field-editor-rich-text:

<ConnectedRichTextEditor
sdk={sdk}
value={accordion.content}
onChange={(e: any) =>
setGlobalData((prevState) => {
    const newState = [...prevState];
    newState[idx].content = e;
    return newState;
})}
minHeight={"300px"}
/>

When the component first renders it works great, but as soon as I change tab, the editor disappears and never reappears even when I return to the original tab. When the page is reloaded the editor reappears, only to disappear again as soon as a new tab is selected. I also tried to render all the editors together without tabs: what happens is that all the editors have the content of the last rendered editor, which is not ideal.

Here is the full Field component

const Field = () => {
  const sdk = useSDK<FieldExtensionSDK>();
  const [globalData, setGlobalData] = useState<AccordionData[]>(
    sdk.field.getValue() || [{ title: "", content: emptyRTF }]
  );
  const [currentTab, setCurrentTab] = useState("accordion-0");

  useEffect(() => {
    sdk.window.startAutoResizer();
  });

  useEffect(() => {
    if (globalData && sdk.field.getValue() !== globalData) {
      sdk.field.setValue(globalData).then();
    }
  }, [globalData, sdk.field]);

  return (
    <>
      <Note style={{ marginTop: "10px", marginBottom: "20px" }}>
        You can create more than one accordion in this component. Use "Add
        Accordion" to create one. If you want to delete a particular accordion
        you can use the "Delete Accordion" button of the relative Accordion.
      </Note>
      <div
        style={{
          display: "flex",
          justifyContent: "center",
          alignItems: "center",
        }}
      >
        <Button
          style={{ marginBottom: "20px" }}
          variant="primary"
          onClick={() => {
            setGlobalData((prevState) => [
              ...prevState,
              { title: "", content: emptyRTF },
            ]);
            const currentIdx = parseInt(currentTab.split("-")[1]);
            setCurrentTab(`accordion-${currentIdx + 1}`);
          }}
        >
          Add Accordion
        </Button>
      </div>
      <Tabs currentTab={currentTab} onTabChange={setCurrentTab}>
        <Tabs.List>
          {globalData.map((accordion, idx) => {
            return (
              <Tabs.Tab panelId={`accordion-${idx}`} key={`accordion-${idx}`}>
                A. # {idx + 1}
              </Tabs.Tab>
            );
          })}
        </Tabs.List>

        {globalData.map((accordion, idx) => {
          return (
            <Tabs.Panel id={`accordion-${idx}`} key={`accordion-${idx}`}>
              <h2 style={{ marginTop: "20px", marginBottom: "10px" }}>Title</h2>
              <TextInput
                value={accordion.title}
                onChange={(e: any) =>
                  setGlobalData((prevState) => {
                    const newState = [...prevState];
                    newState[idx].title = e.target.value;
                    return newState;
                  })
                }
                title={"Header"}
                placeholder={"Header"}
              />
              <h2 style={{ marginTop: "30px", marginBottom: "10px" }}>
                Content
              </h2>
              <ConnectedRichTextEditor
                // @ts-ignore
                sdk={sdk}
                value={accordion.content}
                onChange={(e: any) =>
                  setGlobalData((prevState) => {
                    const newState = [...prevState];
                    newState[idx].content = e;
                    return newState;
                  })
                }
                minHeight={"300px"}
              />
              <div
                style={{
                  display: "flex",
                  justifyContent: "end",
                  alignItems: "center",
                }}
              >
                <Button
                  style={{ marginTop: "20px" }}
                  variant="negative"
                  onClick={() => {
                    setGlobalData((prevState) => {
                      const newData = [...prevState];
                      newData.splice(idx, 1);
                      return newData;
                    });
                    const currentIdx = parseInt(currentTab.split("-")[1]);
                    setCurrentTab(
                      `accordion-${currentIdx >= 1 ? currentIdx - 1 : 0}`
                    );
                  }}
                >
                  Delete Accordion
                </Button>
              </div>
            </Tabs.Panel>
          );
        })}
      </Tabs>
    </>
  );
};

Is there something I’m doing wrong when rendering the editors? Or is this a bug of the editor? Version 1 did not have this problem using the same code structure, but it did have problems selecting the text and changing it.

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:2
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

3reactions
niclaszllaudicommented, Jul 12, 2022

Hi, I encountered the same issue with basically the same use case. After some debugging I tracked down the issue to the ids of the respective ConnectedRichTextEditors. Internally they are passed to the Plate component, which requires the ids to be unique. I was able to fix the issue by passing a unique id to our custom ConnectedRichTextEditor implementation which replaces the internal id calculation.

Unfortunately there doesn’t seem to be a fix available without rewriting the internal rich text editor logic.

2reactions
giovanni-caiazzocommented, Jul 12, 2022

Thank you so much @niclaszllaudi for pinpointing the issue in the codebase. I have used patch-package to make it work. This however is NOT a solution to the issue and if the devs want us to make a PR I would happily do it. For now my project is not blocked though, which is great.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Rich Text field tips and tricks from the Contentful DevRel team
We always recommend using a Rich Text renderer package provided by Contentful to speed up your process when working with the Rich Text...
Read more >
Rendering linked assets and entries in the Rich Text field
Exploring the Rich Text field editor. Now that we're familiar with how Contentful returns items and their linked entries and assets, ...
Read more >
Rendering Contentful Rich Text with Javascript
This article details how to use Contentful's JavaScript client library and the rich text html renderer to render rich text fields as html....
Read more >
Tables in Rich Text fields now available, no reservations needed
Tables have arrived in the Contentful editor and we're pretty excited about it. ... We're going to lay it all on the table....
Read more >
Contentful's React Rich Text Editor: Modeling Interactive Content
In our Contentful setup, we have a content type called “Article” with a Markdown body field. This field contains a bunch of text...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found