For Example:
"I am navigating from page A to page B.On page B I clicked the back button of the browser which should land me back to page A but I need to avoid API calls for page A through clicking the back button of the browser."
If you are referring to "API calls that are sent as a result of loading the JavaScript for page A", then you will want to utilize localStorage to save the information in the browser across page loads. To implement this, you will have to provide logic that checks localStorage for the "cached" information before calling an API for the data. That way, if your user hits the back button on the browser, the JavaScript will check that there is already data from the API in localStorage and then skip making the API call.
Note: you will need to localStorage.clear() or localStorage.removeItem('itemKey') to remove the item if you want to clear the "cached" data. This logic will depend on your use case.
An example could be as follows:
#Component({
selector: 'app-hero-list',
templateUrl: './hero-list.component.html'
})
export class HeroListComponent implements OnInit {
constructor(private heroService: HeroService) {}
ngOnInit() {
if (!window.localStorage.getItem('myData')) {
this.heroService.loadData().subscribe(
(data) => window.localStorage.setItem('myData', JSON.stringify(data))
);
} else {
// Load the data by parsing the stored JSON string:
// const data = JSON.parse(window.localStorage.getItem('myData'))
}
}
}
Is your page a & page b part of the same angular site ? If so then you can store your array as global object in the service layer. When you go back to page b, just access the value and if not null then do not make service calls. Another option is to use local storage as described above
Is there a way to force a React-Router <Link> to load a page from path, even when the current location is already that page? I can't seem to find any mention of this in the react-router documentations.
We have a page on a route for "apply" that loads up a landing page with a hero image, some explanatory text, etc., and an "apply for this program" button that swaps in content that acts as an application form. This all happens on the same "apply" route, because users should not be able to directly navigate to this form without first hitting the landing page.
However, when they have this form open, and they click on the apply link in the nav menu again, the entire page should reload as it would on first mount, getting them "back" (but really, forward) to the landing page again.
Instead, clicking the <Link> does nothing, because react-router sees we're already on the "apply" page, and so does not unmount the current page to then mount a different one.
Is there a way to force it to unmount the current page before then mounting the requested page, even if it's for the page users are supposedly already on? (via a <Link> property for instance?)
Note: this question was posted when React-Router meant v5, and while the problem in this post is independent of a specific React-Router versions, but the solutions are not. As such, the accepted answer is the solution for React-Router v6, so if you're still using v5, first and foremost upgrade your version of React-Router, but if you absolutely can't, the accepted answer won't work for you and you'll want this answer instead.
In the Route component, specify a random key.
<Route path={YOURPATH} render={(props) => <YourComp {...props} keyProp={someValue} key={randomGen()}/>} />
when react see a different key, they will trigger rerender.
A fix I used to solve my little need around this was to change the location that React-Router looks at. If it sees a location that we're already on (as in your example) it won't do anything, but by using a location object and changing that, rather than using a plain string path, React-Router will "navigate" to the new location, even if the path looks the same.
You can do this by setting a key that's different from the current key (similar to how React's render relies on key) with a state property that allows you to write clear code around what you wanted to do:
render() {
const linkTarget = {
pathname: "/page",
key: uuid(), // we could use Math.random, but that's not guaranteed unique.
state: {
applied: true
}
};
return (
...
<Link to={linkTarget}>Page</Link>
...
);
}
Note that (confusingly) you tell the Link which values you need pass as a state object, but the link will pass those values on into the component as props. So don't make the mistake of trying to access this.state in the target component!
We can then check for this in the target component's componentDidUpdate like so:
componentDidUpdate(prevProps, prevState, snapshot) {
// Check to see if the "applied" flag got changed (NOT just "set")
if (this.props.location.state.applied && !prevProps.location.state.applied) {
// Do stuff here
}
}
Simple as:
<Route path="/my/path" render={(props) => <MyComp {...props} key={Date.now()}/>} />
Works fine for me. When targeting to the same path:
this.props.history.push("/my/path");
The page gets reloaded, even if I'm already at /my/path.
Based on official documentation for 'react-router' v6 for Link component
A is an element that lets the user navigate to another page by clicking or tapping on it. In react-router-dom, a renders an accessible element with a real href that points to the resource it's linking to. This means that things like right-clicking a work as you'd expect. You can use to skip client side routing and let the browser handle the transition normally (as if it were an ).
So you can pass reloadDocument to your <Link/> component and it will always refresh the page.
Example
<Link reloadDocument to={linkTo}> myapp.com </Link>
At least works for me!
Not a good solution because it forces a full page refresh and throws an error, but you can call forceUpdate() using an onClick handler like:
<Link onClick={this.forceUpdate} to={'/the-page'}>
Click Me
</Link>
All I can say is it works. I'm stuck in a similar issue myself and hope someone else has a better answer!
React router Link not causing component to update within nested routes
This might be a common problem and I was looking for a decent solution to have in my toolbet for next time. React-Router provides some mechanisms to know when an user tries to visit any page even the one they are already.
Reading the location.key hash, it's the perfect approach as it changes every-time the user try to navigate between any page.
componentDidUpdate (prevProps) {
if (prevProps.location.key !== this.props.location.key) {
this.setState({
isFormSubmitted: false,
})
}
}
After setting a new state, the render method is called. In the example, I set the state to default values.
Reference: A location object is never mutated so you can use it in the lifecycle hooks to determine when navigation happens
I solved this by pushing a new route into history, then replacing that route with the current route (or the route you want to refresh). This will trigger react-router to "reload" the route without refreshing the entire page.
<Link onClick={this.reloadRoute()} to={'/route-to-refresh'}>
Click Me
</Link>
let reloadRoute = () => {
router.push({ pathname: '/empty' });
router.replace({ pathname: '/route-to-refresh' });
}
React router works by using your browser history to navigate without reloading the entire page. If you force a route into the history react router will detect this and reload the route. It is important to replace the empty route so that your back button does not take you to the empty route after you push it in.
According to react-router it looks like the react router library does not support this functionality and probably never will, so you have to force the refresh in a hacky way.
I got this working in a slightly different way that #peiti-li's answer, in react-router-dom v5.1.2, because in my case, my page got stuck in an infinite render loop after attempting their solution.
Following is what I did.
<Route
path="/mypath"
render={(props) => <MyComponent key={props.location.key} />}
/>
Every time a route change happens, the location.key prop changes even if the user is on the same route already. According to react-router-dom docs:
Instead of having a new React element created for you using the
component prop, you can pass in a function to be called when the
location matches. The render prop function has access to all the same
route props (match, location and history) as the component render
prop.
This means that we can use the props.location.key to obtain the changing key when a route change happens. Passing this to the component will make the component re-render every time the key changes.
I found a simple solution.
<BrowserRouter forceRefresh />
This forces a refresh when any links are clicked on. Unfortunately, it is global, so you can't specify which links/pages to refresh only.
From the documentation:
If true the router will use full page refreshes on page navigation. You may want to use this to imitate the way a traditional server-rendered app would work with full page refreshes between page navigation.
Here's a hacky solution that doesn't require updating any downstream components or updating a lot of routes. I really dislike it as I feel like there should be something in react-router that handles this for me.
Basically, if the link is for the current page then on click...
Wait until after the current execution.
Replace the history with /refresh?url=<your url to refresh>.
Have your switch listen for a /refresh route, then have it redirect back to the url specified in the url query parameter.
Code
First in my link component:
function MenuLink({ to, children }) {
const location = useLocation();
const history = useHistory();
const isCurrentPage = () => location.pathname === to;
const handler = isCurrentPage() ? () => {
setTimeout(() => {
if (isCurrentPage()) {
history.replace("/refresh?url=" + encodeURIComponent(to))
}
}, 0);
} : undefined;
return <Link to={to} onClick={handler}>{children}</Link>;
}
Then in my switch:
<Switch>
<Route path="/refresh" render={() => <Redirect to={parseQueryString().url ?? "/"} />} />
{/* ...rest of routes go here... */}
<Switch>
...where parseQueryString() is a function I wrote for getting the query parameters.
There is a much easier way now to achieve this, with the reloadDocument Link prop:
<Link to={linkTarget} reloadDocument={true}>Page</Link>
you can use BrowserRouter forceRefresh={true}
I use react-router-dom 5
Example :
<BrowserRouter forceRefresh={true}>
<Link
to={{pathname: '/otherPage', state: {data: data}}}>
</Link>
</BrowserRouter>
Solved using the Rachita Bansal answer but with the componentDidUpdate instead componentWillReceiveProps
componentDidUpdate(prevProps) {
if (prevProps.location.pathname !== this.props.location.pathname) { window.location.reload();
}
}
You can use the lifecycle method - componentWillReceiveProps
When you click on the link, the key of the location props is updated. So, you can do a workaround, something like below,
/**
* #param {object} nextProps new properties
*/
componentWillReceiveProps = (nextProps)=> {
if (nextProps.location.pathname !== this.props.location.pathname) {
window.location.reload();
}
};
To be honest, none of these are really "thinking React". For those that land on this question, a better alternative that accomplishes the same task is to use component state.
Set the state on the routed component to a boolean or something that you can track:
this.state = {
isLandingPage: true // or some other tracking value
};
When you want to go to the next route, just update the state and have your render method load in the desired component.
Try just using an anchor tag a href link. Use target="_self" in the tag to force the page to rerender fully.
I have an SVG map of the U.S., and I would like to make it so that when you click on a state, a new page loads with information about that state.
Here is my code that fills the states (the paths are already created); it's a choropleth so the color is based on murder rates.
d3.selectAll("path")
.attr("fill", function(d) {
return color(murderrates[codes.indexOf(this.id)])
})
.on("click", **load(new page, this.id)**)
The pseudo code between the asterisks is what I'd like to accomplish: when the state is clicked, open a new page and tell it which state was clicked so it knows what information to display. In other words, the new page should be able to "accept an argument" - the state - so it knows what to display.
Edit: I do not have a different page to load for each state. Instead, it is one page that could display 50 different things depending on which state caused it to load. So let's say I had a variable called origin in my new page. I would like the value of origin to be set to this.id upon loading.
Building off of #StephenThomas's comment, you can define a function loadPage that uses this.id to change the window.location:
function loadPage(){
window.location = URL + "?origin=" + this.id;
}
This will open a new page where the query parameter "origin" will contain this.id. You can then parse the query param, e.g. like this.
Then pass that function as the callback to the onclick, as D3 will automatically set the value of this to the appropriate element:
.on("click", loadPage)
There's so many questions regarding Facebook's sharer.php, but they're all out of date. At first Facebook depreciated it, but according to FB's dev documentation it's now back. (Edit: And now it's going again...?)
You used to be able to use it like this:
http://www.facebook.com/sharer/sharer.php?u=<url to share>&t=<message text>
But the documentation now only mentions this:
https://www.facebook.com/sharer/sharer.php?u=<url to share>
Is it possible to set some pre-entered text into the dialogue box that appears when sharing a link on Facebook?
Thanks.
The Share dialog takes only the URL to share as parameter, nothing else (title, description, picture, …) any more. It fetches this data from the URL itself, from the Open Graph meta elements embedded into the document, or it takes a “guess” from the content if those are not present.
And even the “older” version of the Share dialog has not been taking a pre-set message parameter for a long time now – because you are not supposed to pre-fill the message in any way when sharing something, not matter what way the share actually happens. (“Not supposed to” actually meaning, Platform Policies explicitly forbid you from doing so.)
You can of course also share links via API (rather called “posting” a link then) – and because that happens in the background, the message is a parameter you specify while doing so. But the same rules apply – the message is supposed to be created by the user themselves beforehand, which effectively means they should have typed it in somewhere before. And even there it should not have been pre-filled so that they just have to press enter or click a button.
And since they announced API v2.0, all new apps will have to go through “login review” before they will be able to ask for any advanced permission (and posting a link requires one) – and with a pre-filled message in your app’s posting flow, you will definitively not get approval. Of course, you could try to “cheat” on that, and implement the pre-filling of the message only afterwards … but again, doing so is a clear violation of Platform Policies, and will get your app blocked when you are caught doing so.
And if you are planning to do this for multiple users with the same or largely similar messages, you can assume that Facebook’s algorithms will catch that quite easily.
Just one small comment - while it is not possible to edit the text as the other comments say - it is possible to edit everything going on in that page if you can install a browser extension on your client's machines (you did not specify your use case so I am mentioning this just in case you are developing something that you are able to influence in the client machine level).
For example, with a chrome extension, you can inject scripts into facebook.com domain. in the extension manifest.json:
"content_scripts": [
{
"matches": ["https://*.facebook.com/*",
And then this might be your contnet script, where you can play around with the text by hooking up to the markeup. This example sends out analytics (facebook sharer conversion rate) and changes some text (from "share" to "upload" to facebook):
sharer = (function () {
var _ref = qs('ref') ? qs('ref') : 'unknown';
function qs(name) {
name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
function isSharer() {
return location.pathname === '/sharer/sharer.php';
}
function bindEvents() {
$('button[name="share"]').click(function() {
analytics.send('fb_sharer', 'share', _ref);
});
$('#u_0_0').click(function() {
analytics.send('fb_sharer', 'cancel', _ref);
});
}
function changeText() {
console.log($('.fcw').length);
$('.fcw').text('Upload to Facebook');
}
function load() {
if (!isSharer()) return;
changeText();
analytics.send('fb_sharer', 'view', _ref);
bindEvents();
}
return {
load: load
}
})();
I've made an extension who's purpose is to redirect urls.
I.e: www.google.com becomes: www.mysite.com/?url=www.google.com
I came across this post:
How to modify current url location in chrome via extensions
The problem I'm having is that the url's are both processed. The tab initially loads up google.com and only after it's finished my request is shown ( www.mysite.com/?url=www.google.com).
Is there any way to stop the initial request from being processed?
Something like:
chrome.tabs.onUpdated.addListener(function(tabId,obj,tab){
update.stop() // ??????????? Here I'm missing...
chrome.tabs.update(tabId,{url:....}, function callback); // My update stuff..
});
Thoughts?
thank you all.
You're looking for the webNavigation API.
You can register listeners to handle user navigation by modifying or blocking the request on the fly.
In the example below, when a user navigate to www.google.com, before the page even start loading onBeforeNavigate is fired and you can redirect the user to the CSS validation page for that URL:
chrome.webNavigation.onBeforeNavigate.addListener((details) => {
if(details.url.indexOf("www.google.com") !== -1)) {
chrome.tabs.update(details.tabId, {
url: "https://jigsaw.w3.org/css-validator/validator?uri=" + details.url
});
}
});
Remember to add the "webNavigation" permission to your extension manifest to get this functionality enabled.
chrome.tabs.onUpdated is fired two times per tab load - once a tab starts loading, and another time when it finishes loading. If you attach your update to the tab start loading event then it should work relatively quickly. You will still see original url being loaded for a brief moment, but it won't wait until it finishes, as you are describing.
chrome.tabs.onUpdated.addListener(function(tabId,obj,tab){
if(obj.status == "loading") {
chrome.tabs.update(tabId,{url:....}, function callback);
}
});
I don't think there is a more efficient solution at the moment.