How to have react-router in electrode app push in an action file - react-router

I have a react app using the walmart electrode framework with uses react router. My question is
a) how can push a route during an action trigger? I tried importing push from react-router but I got a method not found error. I tried instead to use browserHistory.push and that sets the url but for some reason login renders only at /#/login?_k=jazzx rather than at /login.
b) how can I get it to do the /resoure urls rather than the hash #/resource urls. It's a single page app. I realize that it's doing that because its a single page app, but Is there a setting for that? Whats the best practice?
c) what is the querystring that electrode is attaching to things - is that for dev only?
export const tryLogin = (returnUrl = '/') => {
return (dispatch) => {
browserHistory.push('/login'); //this doesn't seem to render the route /#/login_k=somestring does work
return dispatch(createLoginAction({ returnUrl }));
};
}
;

The URL /#/login?_k=jazzx implies that you are using a hash history, but you are attempting to change the URL using browserHistory. You should be passing the browserHistory to your <Router> if you want to use the browser history API (aka have clean URLs).
If you use the browserHistory, you will need to have some sort of code on your server to handle routing set up.

Related

Dynamic routing with next export mode

We're using Next.Js in next export mode (static HTML export), and we need advanced dynamic routing.
Our routes will look like /[config1]/[config2]/[optionalConfig?]/page, where one segment is optional and the page names are fixed. For example a/b/c/page1 or a1/b1/page2. The pages need the configuration segment data to render.
I haven't found any way to do this with the built-in routing. I can do /pages/[config1]/[config2]/page1.tsx, but that optional segment seems to be an issue. Note that a custom server does not appear to be an option, as we have to use next export mode due to other constraints.
NOTE: We don't know the paths at build time; they represent part of our runtime configuration. This has to use client-side routing. (We do know the finite set of pages - say page1 ... page10 - but the routes to those pages will vary.)
I've tried switching to React Router, setting useFileSystemPublicRoutes: false and adding routes to pages/_app.tsx (Custom App). That almost works, but I see many 404s for on-demand-entries-utils.js in the console as well as some "Possible EventEmitter memory leak detected" warnings (in development mode).
Valid solutions (must work 100% client-side):
Way to do this with built-in routing
Example of integrating React Router with Next.Js
Alternative library (I've looked at next-routes but that hasn't been updated in 3 years)
UPDATE
We may be able to eliminate the requirement of an optional segment. However, it appears that we have to implement getStaticPaths and specify all of the routes. For example:
pages/[config]/foo.tsx
export async function getStaticPaths() {
// Runs at build time
return {
paths: [{ params: { config: 'xyz' } }],
fallback: false,
};
}
export async function getStaticProps(context) {
return {
props: {},
};
}
export default function FooPage(): JSX.Element {
return <div>FOO</div>;
}
This will generate
┌ ○ /
├ /_app
├ ● /[config]/foo
├ └ /xyz/foo
The issue is that we do not know the config at build time.
We need dynamic client-side routing. We'd like to stay with Next.js, as eventually we may be able to use SSR, but that's not an option at the moment.
You can create a catch-all route to grab the parameters, including the optional one, and then you'll need to render the right component based on that. So if you created:
pages/[...config].tsx
This is the same as:
pages/[...config]/index.tsx
Then in index.tsx, you can get the config as an array of strings in getStaticProps based on the url. So /config1/config2/optional is [config1, config2, optional] and /config1/config2 is [config1, config2].
So you can use this as a directory path of sorts if you need to add additional subpages under the known and optional paths.

How to resolve dynamic routes on client side in Next js framework

I am currently on Next js using full static generation, as I want to serve all my pages from the S3 + cloudfront (no server involved). Next js has good support for this except when it comes to dynamic pages (ex: /posts/:id). All the framework features to solve this type of scenario involve either rendering all passible pages at build time (which is not viable) or having a server to render these pages that have dynamic routes (making, therefore, the site an hybrid app).
To continue to be full static I need to have a way around this.
In create react app one could use the react-router and resolve the routes on the client side, which is exactly what I want to do for the dynamic routes. But I as far as I know next js and the react-router are not compatible, so apparently that is not an option.
Based on what I know, I think Dynamic Route on SSG is supported. Dynamic route feature is independent of getServerSideProps or getStaticProps. you can just use next/router to get the param you need and render your page accordingly.
Here is the official example.
import { useRouter } from 'next/router'
const Post = () => {
const router = useRouter()
const { pid } = router.query
return <p>Post: {pid}</p>
}
export default Post
Reference
https://nextjs.org/docs/routing/dynamic-routes

Universal routing with express and react router. Understanding history behaviour

I am using React Router 4.0 and Express 4.14 to create an app that has a mix of single-page-app (SPA) and multi-page-app (MPA). I don't know if that's good practice, but this is not the point. I am actually doing it to learn rather than for a real world app. This idea comes from the scenario where you have strongly separated sections inside an app, as for example a blog and a portfolio.
Client side
So, when I want to navigate as a SPA, I use the Link component from react-router-dom, like <Link to="/reactrouter-route">. If I want to make a request to a route handled by the server, I use <a href="/server-route">.
Server side
I have a middleware logging the path of any request received by my server. I define two routes, each serving a complete SPA. To keep with the blog/portfolio example, imagine I have the following
const express = require('express');
const app = express();
app.use((req, res, next) => {
console.log(req.path);
next();
});
app.get('/', (req, res) => {
res.sendFile('blog.html');
});
app.get('/portfolio', (req, res) => {
res.sendFile('portfolio.html');
});
Behaviour
When I go to / the blog gets loaded as a SPA and I can go to the different posts navigating back to / when I want. Everything works as expected. All this navigation inside the SPA is managed by React Router, and the server only gets the first request to /.
Imagine that from a specific post, say /posts/some-post, I have a link to the portfolio. If I click it, I get a request at the server, and it responds with the portfolio SPA. I can navigate inside the portfolio SPA, but I cannot go back to /posts/some-post. I get the following error:
Cannot GET /posts/some-post
I thought the error was thrown by the server, but surprisingly I don't get any request when going back. I only get requests at the server when going forward through a link (only with <a>).
I kept doing tests and there is no problem if I go back from /portfolio to /. This works as expected.
It gets interesting
I defined a route in my server with just the same rule that I had in my React Router routes. The path I was matching in this new route was /posts/:postid. I set this route to redirect to /. Now, I get the same error if I go from posts/some-post to /portfolio and I try to come back. This is not strange as the server doesn't get a request. It's also normal that I reach / if I go straight to /posts/some-post by typing in the URL in the browser.
But, once I go to /posts/some-post manually, I can go from /portfolio back to /posts/some-post without the error. Now it behaves as if the server was called. In fact, I get a request in the server to fetch the static files. However, I don't get a request to /posts/some-post nor /.
Even then, I would get an error if a go from /posts/some-other-post to /portfolio and try to go back.
Question
I guess this has to do with the cache, but I don't know what is going on there. When is the React Router handling going back? When is the server handlin it? How is the cache involved in this process?
It sounds like you need a clearer mental model of the roles of the server and the client in an SPA. "Single Page" is the important part.
The client, built with React, should never be loading pages from the server. It should be a "single page". In other words, you should not be using <a href="/server-route"> in your client app at all. The client should only get (JSON) data from the server using something like fetch (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API).
I highly suggest you check out Create React App which also explains how to integrate with a node API backend during development. Basically you want all your client routes to be something like /post/:postid which will be handled by React Router and then that React component would use fetch to get the data from something like /api/posts/10. If you use /api to prefix all your requests to the server it should help your mental model.

Read file at startup Chrome extension/kiosk app

I'm currently developing my first Chrome app that we'll be used as a Kiosk app later.
I'm trying to read a file at the startup of the app, that file is a config file (.json). It contains values that will be passed inside a URL once the app has launched (ie: www.google.com/key=keyValueInTheJsonFile).
I used https://developer.chrome.com/apps/fileSystem (the method "chooseEntry" especially) to be able to read a file, but in my case I would like to directly specify the path/name of the file and not ask the user to select a file. Like that I can pass the values to the redirected URL at the startup.
Any idea of how I could possibly do that?
Thanks!
If your file is in the package you can read it using simple XHR or Fetch.
You can't use web filesystem since it has different purpose and Chrome filesystem (user's FS) won't work here either since it needs a user interaction.
Use function getURL to get a full URL to the resource and then make XHR call:
var rUrl = chrome.runtime.getURL('file.json');
fetch(rUrl).then((response) => {
return response.json();
})
.then((fileContent) => {
// the content
})
.catch((cause) => console.log(cause));

Polymer - url rooting after deployment to subdirectory

Ive created a basic Polymer app from the starter kit (via Yeoman). I've today deployed it to the 'sandbox' on my domain and am getting a strange routing issue. The app is essentially a feed reader.
View app here
When I first visit the app I'm given a blank page whereas locally I'm taken straight to the feed. When clicking on 'News Feed' I'm then taken to the feed as expected.
I've added a route for the path of the domain structure as below but this did not fix it.
You can view the full code of the project here.
routing.html
page('/', function () {
app.route = 'home';
});
page('http://purelywebdesign.co.uk/sandbox/f1feedreader/', function () {
app.route = 'home';
});
I've also tried:
page('/sandbox/f1feedreader/', function () {
app.route = 'home';
});
Any help much appreciated.
Page.js allows you to configure the base path:
page.base('/sandbox/f1feedreader/');
or just use window.location if you don't want to tie is to that specific deployment.
page.base(window.location.pathname);
This is an issue with the way the router page.js works. I assume you were testing with gulp serve (which creates a server and sets the web app base url of "/" to be localhost:3000/). The way you're currently setting your page.js routes is that it's looking exactly after the domain name and not at the "root" of the web directory.
In your case page.js is looking at everything after http://purelywebdesign.co.uk/ (meaning all your routes include should start from sandbox/f1feedreader instead of just /f1feedreader).
The documentation for page.js https://visionmedia.github.io/page.js/ says that it uses regular expressions so you could also update the strings.