Routing an user in a single page application using the adress bar - reactjs

I have a backend using express to serve a static directory, to the path /, in which is contained a single page frontend. This backend also serves an API REST.
The frontend is built in React, and uses react-router to route the user from the different views of the web application.
If my react-router have two entries, let say /app and /config,
how can I redirect the client to that view of the application, if the user enters directly the URL in the web browser's address bar?
Right now, if I do that, Express gets the request and obviously returns a 404 message, as the single page is served to / path.

A simple way to resolve that is to always (even on 404s) send to user the index.html in your express route handlers.
See: https://stackoverflow.com/a/25499007/2624575
However, you need to take care of some things:
1) Your React Router code should start to handle 404s: https://stackoverflow.com/a/37491381/2624575
2) You need to handle correctly the path to your assets (icons, css, js, etc), otherwise you'll send the same index.html to those kind of resources (which will make your page render incorrectly)
3) Make sure that react-router is using browserHistory (the history that doesn't use hashes #), This way React will be able to render your routes correctly
Hope it helps!

Related

How to pass query string from Shopify to an embedded app?

I'm building a Shopify app with Next.js and I need to grab the query string so I can check in getServerSideProps the identity of the merchant (bear in mind that Cookies are not recommended for Shopify apps)
When visiting some apps I noticed some of them are getting the query string passed down from Shopify in each request.
This image shows how it should look on each request
This image shows how my app behaves
In this image you can see that when you hover the routes no query strings are present, meaning that are passed somehow by the parent app.
As of right now I'm using a Cookie to pass the shopOrigin but I feel like it's not necessary if somehow I'm able to get the query string in each request, also with the HMAC I will be able to verify that the requests are coming from Shopify.
Any calls to your App originating from Shopify properly provide the shop parameter when they make requests. In your own App calls to itself, you would also likely be using the shop name as a query string value.
Note that you are still able to validate your sessions internally using a cookie, you just don't do it via the third-party route, outside the iframe, like we used to. Shopify has plenty of documentation on how to properly authenticate, and construct Apps, check them out. They even give you a working Node App to play with, so you can ensure you get it right.
The solution was pretty straightforward.
Shopify provides a TitleBar AppBridge component that you can use to to handle the App's navigation. What it does is that on each route change it reloads the iframe and the hmac, shop, code and timestamp are coming in the request. It's a tad slower then client side routing but it works as expected.
In order to use it you just need to go to:
Partner's dashboard / Your App / Extensions / Embedded App (click Manage) / Navigation (click Configure) and add navigation links, then you just need to import TitleBar from app-bridge-react and put it in index.js

Is it OK settings location.href to force routing on the server-side?

I'm working on a React web app with an Asp.Net Core + Typescript back-end. The routing is on the front-end, managed by the React-Router v4. Everything is working fine so far.
By the way, there are cases where I need (I want) to redirect the routing by the server instead to let it to the browser logic. For instance, I want to force the redirection to a certain page when a cookie is not present or expired.
As just for instance, if I use something like <Redirect to="/reserved" /> the React.Router does its best: routes toward the "reserved" page, but that's not what I want. I need this path supplied to the server, i.e. kind of bypassing the front-end routing.
In such cases, the solution I found is to set the desired path as follows:
window.location.href = '/reserved';
That seems sending the new path request straight to the server with no (apparent) involvement with the React.Router. Apparently, everything works fine, as I expect.
The question is: is it a reliable way to achieve the desired behavior, or it looks much likely a hack (and I should avoid it)?
Within the context of a single-page application (SPA), regardless of the framework or technology you are using, setting window.location explicitly is a perfectly fine way to leave the routing control of the SPA and force the browser to make an actual HTTP request for that new route.
Doing so of course means that the whole page will unload, so when doing that, you are leaving your SPA. If that target URL then loads the same SPA again, this will usually be distracting to the user. That is why common SPA router implementations will intercept route changes and handle them through their own routing instead of having the browser make an actual request.
You should check your router’s documentation to see if you can add some router guards that allow you to verify things on load or on route changes, so you can navigate the user away to some forced location.
If that target URL is not part of the SPA, then of course setting window.location is perfectly fine. It’s certainly not a hack but rather just the proper way to change the location without going through the SPA’s router.

Is there a way to "Break out" of a react app with a relative link

Context
We have 2 distinct React JS applications both deployed behind a proxy.
The proxy serves one app (let's call it the home page) on the root / location. It serves the other on a subpath, e.g. /application-a/. Both are therefore on the same domain, e.g. https://my-site.com/ and https://my-site.com/application-a/
This works great if I open 2 new browser windows and navigate 1 directly to / and the other directly to /application-a/.
The problem comes when I might want to use a HTML a tag inside the root path application (home page) and link this to the application running at /application-a/ subpath using a relative href.
In this case I believe that the router kicks in and wants this to be route in the local app. I want to try to "escape" or "breakout" of the react router.
Possible Solutions
I think if the anchor tag href in the root app has a target attribute value of _blank this works ok - but is undesirable as it forces a new tab to be loaded.
If I use an absolute URL for the href value then I think it will "escape" the SPA and access the new page in the same tab. Sounds great - but now I have to use absolute URL's making the code less portable between dev/staging/live etc.
Explicitly put a matching route in the router for /application-a/ and programatically change the window.location? I could see this might work but feels messy to me.
Question
Isn't there a way I can use good old fashioned anchor tags and maybe provided some type of attribute which tells the react router to "leave me alone" and let me behave like a "regular" anchor in a static HTML/non-SPA/non-React JS page. If not, any other advice appreciated.
Similar unresolved question: Navigating out of a react-router single page application on the same host
Can you use a HashRouter instead? https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/docs/api/HashRouter.md
URLs won't be "pretty", but it should work.
Alternatively, you could maybe redirect the user to the other app if the current urls doesn't match with any route definition, e.g.:
<Route render={() => (<Redirect to="http:/full-url-to/other-app" />)}/>
after all your other route definitions, so that it matches only when no other route matches.
About portability between different environments (staging, live, ...), consider you could also use Webpack DefinePlugin to set a variable at build time, so you can pass the base URL dynamically.

How do all react requests go to the index.js file?

I'm a bit confusing how routing works with react-router.
Normally when a request comes to the server for a request like:
http://www.example.com/path/to/file
A request will make it to the server for that file, and then the framework will handle the request.
With react router, how does this work? Do things somehow get intercepted at the client side (browser) and then only a request to index.html will be made to the actual web server?
I'm assuming somehow the request to /path/to/file gets trapped by javascript and only a request to index.html makes it to the server, but how does it do this?
React router is a client side router, so when we do configs for nginx or any webserver in general with react router we specify and send only 1 file known as index.html and then the JavaScript code provided by react router figures out which component to serve by looking at the path and history of the browser.
So no matter which path you request it's indirectly index.html which gets the request but with a different path which then figures out what to do.
One part of the answer is looking at the basename prop of the Router. Everything that comes after that is handled at client side as the location corresponding to the app current state.
Another part of the answer is that when using BroswerRouter (as opposed to a HashRouter that uses the # separator in the URL before the local app state), the server has to serve the app "index.html" for any route that does not correspond to an actual static ressource or an API route. This is usually treated as the fallback behaviour of the server.
When using BrowserRouter, if your server base url is http://example.com/app, and your current app state is /user/12, that makes the current browser url http://example.com/app/user/12. If you refresh your browser, it will make a request to http://example.com/app/user/12 and your server app has to answer with the index.html of the app. When loaded, react router will interpret the current state as /user/12, following the configured basename.
When using a HashRouter, with the same server base url and app state, the current browser url would be http://example.com/app/#/user/12 and when refreshing the page, the browser would make a request to http://example.com/app/

Single Page App on React.js and ZF2. Is it possible?

I'm thinking how to implement a SPA on Zend framework 2 using Reactjs? Haven't seen any tutorial that might help me. So, I was asking if this is possible. How would zf2 will handle the routes?
The routes are handled on the client side (by pushing URLs into browser's history so you can also use browser's back button for navigation)
Simply put, changing a route will not load a whole page from the server.
The server does not even know that your JS app is changing the URL in the browser (imagine you write by hand http://example.com#test while you were already on example.com; that #test thing is a fragment URL and it will never be sent to a server)
Instead, the JS application will respond to (once again, client-side) route changes by rendering a different page or section, and making some ajax calls to the server to fetch or update data.
Now let's see what the server should do:
send the first page (the "single-page") and the assets (CSS, JS) on
the first load
respond to app-originated AJAX API calls once the page is loaded and
the JS app has been started
That's why they call them "single page apps", because they do much of the logic and the presentation in the browser (DOM rendering, routes), and the server merely acts as a data layer, or a backend if you like this word better.

Resources