Ask Questions and Find Answers
Important:
Ask is now read-only. You can review any existing questions and answers, but not add anything new.
But - don't panic! While ask is no more, we've replaced it with discuss - the new Liferay Discussion Forum! Read more here here or just visit the site here:
discuss.liferay.com
RE: Using react-router-dom in portlet
I'm getting an ambiguous error when I import the `react-router-dom` library into my react.js portlet. I can successfully build and deploy, but I get this in the browser console:
Uncaught (in promise) ReferenceError: global is not defined
at module.exports (index.js:7)
at createReactContext (index.js:41)
at createNamedContext (RouterContext.js:5)
at Function.<anonymous> (RouterContext.js:11)
at Loader._setModuleImplementation (loader.js:981)
at defineModules (loader.js:1094)
at loader.js:1113
And here is my import inside `index.es.js`:
import { Switch, Route } from 'react-router-dom';
I can import other libraries (I tried lodash as a test) and can use them just fine. I seem to only have this problem with navigation based packages. Any input would help, thanks!
Uncaught (in promise) ReferenceError: global is not defined
at module.exports (index.js:7)
at createReactContext (index.js:41)
at createNamedContext (RouterContext.js:5)
at Function.<anonymous> (RouterContext.js:11)
at Loader._setModuleImplementation (loader.js:981)
at defineModules (loader.js:1094)
at loader.js:1113
And here is my import inside `index.es.js`:
import { Switch, Route } from 'react-router-dom';
I can import other libraries (I tried lodash as a test) and can use them just fine. I seem to only have this problem with navigation based packages. Any input would help, thanks!
You should probably avoid the router dom, especially if you plan on using the address bar.
In Liferay, your JS portlets do not own or control the address bar, Liferay controls it. Anything you try to include is not bookmarkable (Liferay will generate a 404 on it, I believe, because it is not a valid portal URL), navigation away and back will discard any changes to the address bar, ...
So router is not all that useful in the portal.
In Liferay, your JS portlets do not own or control the address bar, Liferay controls it. Anything you try to include is not bookmarkable (Liferay will generate a 404 on it, I believe, because it is not a valid portal URL), navigation away and back will discard any changes to the address bar, ...
So router is not all that useful in the portal.
<p>So the main problem is that we want to have a single page react portlet. There are "screens" that the user can progress through, and may want to go back by using the back button in the browser. The way I'm handling it now is to just show/hide the screens with css, but this offers no back button functionality. Does this seem like a problem that can be addressed by liferay?</p>
All of these hopes and dreams will fail. Seriously.
Give it a try; navigate to another liferay page and then come back. Even if your URL remains, your react context is totally wiped out. Plus since Liferay manages the address bar, you're more likely to get a 404 response instead of rendering your page w/ the portlet showing the page you expect.
It's not a Liferay issue, btw, it is a perception issue. A Liferay page has a url, such as /web/guest. You can drop any portlet you want on this page, so envision being able to drop two of your "spa" portlets on a page. Imagine they each have a route like #EnterPartNumber.
Now imagine refreshing your page, /web/guest#EnterPartNumber. Which of your two React spas should handle it? There's nothing in the URL indicating one portlet vs another, so how should the portal respond?
And that's if you're using hashes. If you try leveraging slashes, then your URL is /web/guest/EnterPartNumber which Liferay assumes is a path to a page that it should be providing, this will always lead to a 404.
And as always, your React context is only good as long as the user doesn't navigate away or refresh the page. In Liferay, you're not locked into your "SPA" React portlet so you lose control over the context quite easily. If you don't really understand this and don't plan for it happening and build in logic to allow for a smooth recovery, your UX is going to be quite fragile and your users are going to complain.
Give it a try; navigate to another liferay page and then come back. Even if your URL remains, your react context is totally wiped out. Plus since Liferay manages the address bar, you're more likely to get a 404 response instead of rendering your page w/ the portlet showing the page you expect.
It's not a Liferay issue, btw, it is a perception issue. A Liferay page has a url, such as /web/guest. You can drop any portlet you want on this page, so envision being able to drop two of your "spa" portlets on a page. Imagine they each have a route like #EnterPartNumber.
Now imagine refreshing your page, /web/guest#EnterPartNumber. Which of your two React spas should handle it? There's nothing in the URL indicating one portlet vs another, so how should the portal respond?
And that's if you're using hashes. If you try leveraging slashes, then your URL is /web/guest/EnterPartNumber which Liferay assumes is a path to a page that it should be providing, this will always lead to a 404.
And as always, your React context is only good as long as the user doesn't navigate away or refresh the page. In Liferay, you're not locked into your "SPA" React portlet so you lose control over the context quite easily. If you don't really understand this and don't plan for it happening and build in logic to allow for a smooth recovery, your UX is going to be quite fragile and your users are going to complain.
If I understand you correctly: anything that we consider to be its own screen, if we want to be able to return to it with the back button, will have to be its own portlet on its own page? So we will have a series of pages with one portlet each, and the user will just have to request the new page each time they move onto the next screen?
No, it's more that you can't just assume that normal browser-based context can be counted on.
If you need to restore context, that would mean context has to be persisted either in the browser (local storage, session storage, cookies) or server side (web service calls). As soon as you start doing this, though, routing becomes ineffective because you're not able to take advantage of its normal way for switching views; you take over view switching and therefore can discard router.
If you need to restore context, that would mean context has to be persisted either in the browser (local storage, session storage, cookies) or server side (web service calls). As soon as you start doing this, though, routing becomes ineffective because you're not able to take advantage of its normal way for switching views; you take over view switching and therefore can discard router.
I haven't any problem using react-router-dom because I used HashRouter mode
Of course, it works only for one React portlet in a page
Of course, it works only for one React portlet in a page
<hashrouter>
<switch>
<route exact path="/">
<list />
</route>
<route path="/form/:id">
</route></switch></hashrouter>
Only works on one portlet on a page, doesn't work as a bookmark, doesn't work if there is portal (Liferay) navigation to another page and back, ...
Copyright © 2025 Liferay, Inc
• Privacy Policy
Powered by Liferay™