React Router getHistory - reactjs

It is possible to get the list of browser history? For example, if I navigate as follows: page1 -> page2 -> page1 -> page5, I want to be able to get an array of ["page1", "page2", "page1", "page5"] (so effectively history.pop() should give the URL of goBack()

There's no such API definition or implementation in either History object of browser or history library that used by react-router. It will cause some security problems (considering the situation of cross-domain).
However, you can listen for changes of location and store them manually. It won't bring security issues since the operations are all limited in a single domain:
history.listen((location, action) => {
console.log(action, location.pathname, location.state);
// you can store the result anywhere you like
const prevUrls = window.sessionStorage.getItem('prevUrls') || [];
prevUrls.push(location.pathname);
window.sessionStorage.setItem('prevUrls', prevUrls);
})
Then you can use window.sessionStorage.getItem('prevUrls') to get list of history.

Related

Alternative for window.location.href in react for a single-page-application

I have two different react applications, one for customer and one for admin.
Customer app runs on port 3000 and admin on 3001.
I have a button where I want to change from the admin page to the customer page and vice versa.
For now, I am using window.location.href to reload to another url and this works, like this :
onClick={event => window.location.href='http://localhost:3000/customerloginpage'}
I tried redirect and routes and using history but what happens is that it adds the url to the end of the current url instead of replacing ,example :
const history = useHistory();
const customerButtonClicked = () =>{
let path = 'http://localhost:3000/customerloginpage';
history.push(path);
}
Example result :
'http://localhost:3001/adminloginpage/http://localhost:3000/customerloginpage'
Is there a way to do this without having to reload the page with window.location.href? Please explain this concept to me, thanks!

Next.js How to make a redirect correctly

I have such a page structure.
locale can be any value from the language-country pair
eg en-ca, fr-fr, ar-en
[locale] // main folder route
page1.tsx // child route
page2.tsx // child route
page3.tsx // child route
For example, if I go to the address /page1, then I redirect to /locale/page1
But the problem is that I check on the browser side and first a 404 page appears in the browser and only then redirects to the correct address.
I think that it is necessary to check on the server.
I was making my own file for the server. But the problem is that there is no way to track the address for which the request is going and that means I cannot check if the address starts with the parameter I need.
In case you do not wont to use Next.js native i18n routing you can create fallback page file pages/[...fallback].ts to catch all non-existing page. Then you can use use getServerSideProps to redirect properly.
This could work for you (not tested):
// The page content will never be rendered
const FallbackPage = () => <div>Redirecting...</div>
// Is processed on every request on server side
export const getServerSideProps: GetServerSideProps = async (ctx) => {
// TODO: add custom detection (e.g. based on headers or cookies)
const locale = 'en'
const destination = `/${locale}/${ctx.params.fallback.join('/')}`
return {
props: {},
redirect: { destination, permanent: false },
}
}
export default FallbackPage

Programmatically navigate to a dynamic url with gatsby

I am using navigate to move to another URL. I saw many posts using Link to move to another page with dynamic url. But I want to change url without writing jsx
When I navigate to the following url, I get a 404 error
navigate(`/vidx/${u}`, {
state: { vid: r }
})
I changed gatsby-node.js to following, still getting the same error. I have a file named vidx.js in pages folder
exports.onCreatePage = async ({ page, actions }) => {
const { createPage } = actions
if (page.path.match(/^\/vidx/)) {
page.matchPath = "/vidx/*";
createPage(page);
}
}
My url will look like this - www.xyz.com/vidx/123456789. The number 123456789 will depend upon the user logged in
I want to redirect to vidx.js; but the URL should be /vidx/123456789
That will never work since /vidx/123456789 will always throw a 404 error since it's not generated and doesn't exist, it's a separate new page.
One easy thing you can do use: /vidx?queryParameter=123456789. In that case, your page will remain being /vidx and you can get the queryParameter to make your stuff with your own logic.

Catching parameters in redirect with Gatsby.js

I have one quick and dirt question.
Is it possible to catch a query parameter from a server redirect inside of Gatsby.js application?
We have a Pardot tracking link that does redirect to our thank you page which is built in Gatsby.js and I want to pass some query parameters to the application it self from that redirect.
So for example:
www.trackedlink.com/thank-you?programme_code=CODE_FROM_REDIRECT_ON_SERVERSIDE
will redirect to:
www.gatsbyapplicationthatwillreadthequery.com/thank-you?programme_code=CODE_FROM_REDIRECT_ON_SERVERSIDE
Is it possible to read that query inside of the application if it's coming from the outside of the app?
Cheers and have a great week!
If they are triggered in the client-side the redirection will be caught by the application and yes, it would possible if they are coming from outside the app or using a standard anchor. Not using a #reach/router (<Link> component since it's a limitation).
A clean and scalable way to use it is by adding in the function in your gatsby-browser.js configuration:
import React from 'react';
import { checkUrlFunction } from './src/services/yourCheckUrlFunction';
export const onClientEntry = () => checkUrlFunction();
Adding a function in gatsby-browser.js with onClientEntry API will trigger your function once the page is loaded. From the documentation:
onClientEntry Function (_: emptyArg, pluginOptions: pluginOptions) => undefined Called when the Gatsby browser runtime first starts.
Your function should look like:
export const checkUrlFunction = () => {
if (typeof window !== 'undefined') {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const programmeCode= urlParams.get('programme_code')
if(programmeCode) window.localStorage.setItem('programmeCode', programmeCode)
console.log(programmeCode); // will output CODE_FROM_REDIRECT_ON_SERVERSIDE
};
};
Note the typeof window !== 'undefined' necessary to avoid issues if the window object is not defined when triggering the function
Hi Ferran, thank you for your solution but unfortunately, it does not
work when the redirect happens. It only works if the query string is
inside of the application
Yes, the idea of adding the function in gatsby-browser.js is to avoid the addition of checkUrlFunction() in each page, template, or component. The disadvantage is that you lose a bit of control but it saves a lot of overwriting code and improves the scalability and readability.
Thanks, Ferran, if you could show me an example of it - it would be
amazing! This cookie topic is sort of unknown water for me
So, with your specifications updated, I've added the localStorage approach since it's easier to achieve in a non-IDE environment like this, but the idea is exactly the same.
Set a vault (cookie or localStorage) automated in the gatsby-browser.js function
if(programmeCode) window.localStorage.setItem('programmeCode', programmeCode)
This sets a localStorage key/value pair ('programmeCode' (key)/programmeCode (value)
Access to that vault in your component. Use a componentDidMount lifecycle or useEffect hook to ensure that is loaded before the DOM tree is mounted.
useEffect(()=>{
if(typeof window !== undefined) console.log(window.location.getItem('programmeCode')
}, [])

React Router: Go back to specific page

I have a settings page, with a few sub routes:
--/home
--/articles
--/settings
--/Account(default)
--/Help
--/About
I would like it in such a way: when I'm in any one of the sub pages under settings, and the browser go back in history, it should always go to the (default)Account page. Going back again will follow the normal browser history behavior.
What's the best way of handling it?
You can use history:
import createHistory from "history/createBrowserHistory"
const history = createHistory()
history.push("/account")
<Router history={history}/>
After quite some research, it seems there's no easy way of doing it, discussions in react-router github wouldn't disagree. A workaround seems to be the consensus. Which is a bit raw to my liking, but anything that works is good.
So instead of keeping every sub page under settings with their own route(to be handled by react-router), I have them controlled by state in settings component. And the following event handling is used:
componentDidMount = () => {
window.onpopstate= () => {
if(this.state.currentSubPage !== 'account-settings') {
this.props.history.push('/settings');
} else {
window.onpopstate = null;
}
};
}

Resources