Hi!
I stuck with routing in my atlassian connect app.
I have SPA with pages:
<plugin.balse.url>/items - all items are displayed in table with links to every single item
<plugin.balse.url>/items/(id-of-item) - page with single item
when I run this app locally everything is working, but when I deploy my app to my cloud instance, my base url path is changed(because my app is displayed in iframe) to
https://(jira-site).atlassian.net/plugins/servlet/ac/my-plugin/items
All items in the table are shown correct, but when I clicked on the separate item, I recieve 404 error
I think the problem with displaying my app in iframe and (in this case) react-router wouldn’t work here.
I’m not sure about that, so If anyone uses routing in cloud app, please help me
1 Like
We have tried with Hash tag approach in our app and it worked for us.
https://{domain}.atlassian.net/plugins/servlet/ac/{key}/app-entry?project.key=DEMO&project.id=10000#!/Manage/{newpage}
constructor(props) {
super(props);
if (window.AP) {
window.AP.getLocation(location => {
// Below condition is mandatory for reload application on same page
if (location) {
const locParts = location.split("#!");
if (locParts.length > 1) {
this.props.history.push(locParts[1]);
}
}
});
this.props.history.listen(location => {
let loc = location.pathname;
if (window.AP) {
if (location.search) {
loc += location.search;
}
const jiraState = window.AP.history.getState();
if (loc !== jiraState) {
window.AP.history.pushState(loc);
}
}
});
// This will listen instance hash change event and open the page accordingly
window.AP.history.popState(e => {
if (e && e.newURL) {
this.props.history.push(e.newURL);
}
});
}
}
1 Like
Thank you! You helped me a lot!
I appreciate the response but could you be more elaborate here? I assume this is a class constructor that extends some component but which component did you extend?
It’s not so complicated actually. Simply use HashRouter as default router from the router-dom package:
import {
HashRouter as Router,
Route,
Switch,
} from ‘react-router-dom’;
You can use react-router normally then
2 Likes
Does that preserve your location after a page reload? For instance, if I navigate to /some/path in my iframe and then reload the site, will I end up on the same page in my iframe?
for that to work, you need to sync the hash changes with AP.history as outlined in the solution by @umang.savaliya
Nice, will have a look at that. Thanks.
I have tweaked @umang.savaliya’s answer to work with React Router v6 and Typescript. The following is all I needed to persist the location across page reloads.
import React, {PropsWithChildren, useEffect} from 'react';
import {useNavigate, useLocation} from 'react-router-dom';
declare global {
interface Window {
AP: any;
}
}
interface RouterSync {
}
function RouterSync({children}: PropsWithChildren<RouterSync>) {
const navigate = useNavigate();
const location = useLocation();
useEffect(() => {
if (window.AP) {
window.AP.getLocation((location : any) => {
if (location) {
const locParts = location.split("#!");
if (locParts.length > 1) {
navigate(locParts[1]);
}
}
});
}
}, []);
useEffect(() => {
let loc = location.pathname;
if (window.AP) {
if (location.search) {
loc += location.search;
}
const jiraState = window.AP.history.getState();
if (loc !== jiraState) {
window.AP.history.pushState(loc);
}
}
}, [location])
return <>{children}</>;
}
export default RouterSync;
You would then use it as some descendant of HashRouter
like so:
root.render(
<AppContainer>
<HashRouter>
<RouterSync>
<PageLayout>
...
2 Likes