Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

Rendering React components for rich text blocks

default discord avatar
mobeigi6 months ago
5

I'm currently working on a 3.0 branch project where I have a few blocks (

Code

,

Embed

,

MediaBlock

,

FileBlock

). These are available for use in a

Posts

collection I have.



I am displaying these on a blog page using

getPayloadHMR

to get the data and then passing it to a render only react component like

<BlogPost title={title} date={publishedAt} html={htmlContent} />

.



My issue is the lexical rich text field. I am convering it to HTML using a bunch of custom HTML converters I wrote for each block and

lexicalToHTML

on the content then rendering the raw HTML in a div.



However, the limitation here is I have to return a

string

(for the converted HTML) in each of my converters that prevents me from using React components which is what I want to use for various reasons.



My question is what is the best practice for rendering the lexical rich text using React components with support for my custom blocks too?



Played around a little more with it and had a look at examples. I see some examples have a

RichText

component which seems to implement serialization by re-implementing everything (from

text

nodes to

paragraph

etc). What would be nice I think is if the

RichText

component fell back to using the default HTML renderers by default but allowed you to explicitly override certain node types as desired (i.e.

block

).



Going to see if this is possible.



@114557048678514693

Thanks for sharing! Seems like this approach will work but I feel its a bad pattern to use for all the 'default' lexical components.



On the pro side it lets you customise each element to your needs.



On the cons side most of these are already implemented via default html converters. Even if you copy the implementation across you lose out on bug fixes / improvements in future updates.



I still feel the ideal solution would be:


- Custom logic / overrides for things you want


- Fallback to defaulthtml converters



That way you'd also need to write serialisers for your custom block / inlineBlocks but don't every other thing .



However I need to get something up and running so I'll follow your example approach for now 🙂



I had good success converting everything from HTML converters to ReactNode!

@114557048678514693

your code was a big help, thanks 🙂



Most nodes are wroking but some I still need to fix up (like checkbox, relationships).



Here is my current WIP:


https://github.com/mobeigi/mobeigi.com/tree/2024-redesign-payload/app/src/payload

I did make some structure, naming and other edits. I tried to remove all styling as much as possible and keep it very generic.



@360823574644129795

In my opinion, by default Payload should provide both HTML Converters and ReactNodeConverters for all the default lexical node types like

paragraph

,

heading

,

text

etc.



Take a look at the pattern I adopted here:


https://github.com/mobeigi/mobeigi.com/tree/2024-redesign-payload/app/src/payload/converter

In my opinion if payload had

defaultReactNodeConverters

in addition to

defaultHTMLConverters

, users could get started quicker with a powerful

serializeLexical

function out of the box.



Then of course, if needed you can overwrite specific converters and add your own for custom blocks, just as you would for HTML converters.



This would allow people to get started with lexical / rich text much quicker and is a very common use case. Its more than fair to assume almost everyone would want paragraph node support but other opinionated blocks etc should be left out of the default implementation (like custom code blocks etc).



Having to implement such things yourself is annoying.



Can you discuss with the team and let me know your thoughts and if that is a direction the team is happy to go towards? I'd be happy to make a contribute a PR to add this fuctionality into the

beta

branch but only if it will be accepted.



Let me know 🙂



Oh I see so its on the roadmap



I guess your example is basically going to get turned into a default function that is exposed that can be extended etc (basically same as defaultHTMLConverter pattern)



By the way one question, the internal links in your example is broken right?



Ah gotcha, I ended up implementing it



Not sure if ideal but works for my needs:


https://github.com/mobeigi/mobeigi.com/blob/2024-redesign-payload/app/src/payload/converter/customInternalUrlResolvers.ts

What is your project if you don't mind sharing? Is it live?



What kind of website is it?



Hi, thats not really related to this post. Try creating a new post focused on your issue.

  • default discord avatar
    tyteen4a037 months ago

    have a look at my example:

    https://github.com/tyteen4a03/payload-lexical-renderer-example

    you'll need to switch 100% to ReactNodes but I think it's worth it



    On the cons side most of these are already implemented via default html converters. Even if you copy the implementation across you lose out on bug fixes / improvements in future updates.

    Not really, unless Lexical changes how they store data



    yes, payload is working on a native ReactNode renderer setup that can be installed anywhere (even outside Payload) so you wouldn't need my example anymore



    yes



    I did not implement internal links



    for my project my internal links look just like external links, but I can have a look and provide an impelmentation



    CMS for a game



    not live yet

  • default discord avatar
    lzyac7 months ago

    is there a distinction between the node.type of "text" and "paragraph"



    srry ignore figured

  • default discord avatar
    kodaneflash7 months ago

    im trying to implement a form on my payloadcms site, i installed the 'custom form builder' but im getting stuck on how to configure payload to allow a file upload as one of the fields for the form, that or i can just embed the tally.so form

    https://tally.so/embed/123456

    but how do i configure payloadcms to implement an iframe?

  • default discord avatar
    heygio.7 months ago

    change csp.js to allow tally form domain

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get dedicated engineering support directly from the Payload team.