Re-rendering with a custom render function
I'm using a custom render and getRootContainer function in order to mount a custom element directly onto a specific pre-existing div without the use of shadow root (in order to adopt the existing page styles) and to avoid using any typical Plasmo parent elements. However, unlike the default exported component which automatically re-renders when the root is removed and added back in, this custom render does not adopt the functionality. When my custom root container that I've declared is removed from the page and added back in, my custom BetterInput component does not re-render. What is the best way to solve this problem? The following is my code:
7 Replies
I have found a working solution, with reusable functions that automatically enable any component to be directly injected without a shadow root and without parent elements. It is quite large/messy, so I will update it and post the solution later.
Thanks—curious to see what your solution is. Currently facing the same issue and it’s pretty much the last thing left to release my extension
@Alex Godard has reached level 2. GG!
Here's the finished example. I put this in a file called
core.tsx
in a separate directory outside the contents folder.Example usage of a component from my project:
Essentially, it just requires you to to call
coreGetRootContainer
with the parent selector where you want to inject the component, the id that you gave to the component (it's required to give an id in jsx), and then just pass the actual component. The other method is renderComponent
which doesn't require anything custom, just follow the same example to pass a root container element.
How it works: It replaces plasmo's renderer with a custom renderer. This was specifically designed to not use shadow root and inject directly instead to inherit the page styles. After the initial render, there is a DOM observer that gets created to continuously watch all DOM changes. When it finds out that the component no longer exists, but the parent element still does, it will re-inject it. (example - you want to inject a button inside a div. The user is on an SPA so the div disappears along with your button when they move to a new page. Then, they move back to that same page, so it detects that the div showed up again but without the button, so your button gets re-injected). Overall pretty hacky but it worked.
Also leaving this message for anyone else who had issues with Plasmo - I actually just ended up migrating my extension from plasmo to CRXJS today (https://crxjs.dev/vite-plugin). I was able to write the same solution in much less lines of code. Plasmo is also just way too buggy for me - the extension doesn't even update half the time when I edit a file and I often have to manually kill plasmo and restart the process to get it to update. The content UI HMR is also extremely buggy, and doesn't work at all for global css. CRXJS feels much faster and has perfect HMR. It has less features, but more third party libraries are just working out of the box since it uses Vite, and it gives much more control over the DOM which I enjoyed a lot more.It works -- Thank you!!
Kinda nuts that you had to come up with this and that there's no example in the official docs -- This seems like a very common use case