How to work with react-router-dom in Figma plugin

When I use react-router-dom in Figma plugin, the code didn’t render the component, is it because I used a wrong path, anyone has any idea?

    <Router>
        <Switch>
            <Route path="/">
                <Homepage />
            </Route>
        </Switch>
    </Router>

Router is used when switching between different webpages. Plugin iframe is only one page, so you can’t use this here. You need to hide/show different elements via something else. Alternatively you can host this UI somewhere as a website and show it in the iframe, the router should work in this case.

2 Likes

If I host the UI somewhere else, does those messaging between plugin code work as expected?

Yes.

@Gleb @Bahtiyar I’m not sure this solution is necessarily correct. You should be able to use the MemoryRouter from react-router-dom if I’m not mistaken to get a multi-page layout working in the way you expect.

i.e. use import { MemoryRouter as Router } from "react-router-dom". This is how I do it with a Svelte library that is based on React Router and how I’ve used React Router in the past with Chrome Extension popups which have similar limitations to the Figma plugin iframe.

More info here: React Router: Declarative Routing for React.js

3 Likes

@Emile_Paffard-Wray MemoryRouter worked for me!

Hello, I wanna know will there be any issues while publishing the plugin? since the UI is hosted somewhere else

No, that’s not a problem at all.

Hey Gleb!
I tried running the react app locally and serve it through ngrok to get the hosted https website behavior but when i added the code(this file has JS code that receive post messages) and the UI(This is the index.html of react app) URL in the manifest.json file and tried to load the plugin in figma desktop app its kept on giving error saying cannot load code.

<–manifest.js–>
{
“api”: “1.0.0”,
“editorType”: [
“figma”
],
“id”: “<SOME_ID>”,
“name”: “<SOME_NAME>”,
“main”: “<ngrok_url>.com/code.js”, // This file is directly placed in public folder of react app.
“ui”: “<ngrok_url>.com/index.html” // This is the react app public index.html page
}

So, does that mean hosted website approach cannot work or am I doing something wrong?

You are definitely doing something very wrong: you can’t put URLs in the manifest. The files need to be regular local files. From UI HTML you can set window.location in JS to open your website in the iframe.

Okay I was able to do it. Code.js that is the plugin js code receives the postMessages is locally stored and the UI index.html is also locally stored with basic html inside and a javascript code that is window.location = "https://<ngrok_url>";

So, the iframe becomes my react app. But now the question how do I send postMessages from the react app to the plugin code.js can receive it.

Whenever i try to do even console.log(parent) react app doesn’t recognize it and cannot be compiled.

The figma docs say’s if I want to send postMessages from the UI to the Plugin I should do parent.postMessage({ pluginMessage: 'anything here' }, '*')

Thank you Gleb for helping me out here understand the whole process.

Hey @Gleb I was able to figure it out. So, from react app postMessages can be received using

window.parent.postMessage({pluginMessage: "<SOME_DATA>", 
 pluginId: "<FIGMA_PLUGIN_ID>"})

Also, for some reason i had to add the plugin id to the messages as messages were getting ignored from the react app.

Not sure how would the journey of other way around will work plugin to react app postMessage. But for now I don’t want that anyway.

Thank you so much for your help and support. I really appreciate it.

Hey Gleb!

Do you know how can I receive postMessages from the code.js to my plugin which is based on window.location (this is a react app).

It should work the same way as without changing the window location. Test code: Glitch :・゚✧