I am using react router to build a single page app.Now, everything is fine, except remembering the previous status. I mean: each time when user chooses one option in a select dom, then click a link component to jump to another route path; then, if this user clicks back button from browser to go back to the previous page, he can not see his previous choice, everything lost!
The desired behavior you are talking about is about saving the State of the Component. Even though the router renders the desired Component, it does not save the State of that Component.
However, you can pass in a desired State via URL Parameters, but that doesn't like a solution for you due to what exactly you are trying to achieve.
Passing data in through the URL to achieve the state may sound like a good idea, but this won't work due to the URL having to be updated as the User selects different options, and this will trigger new rendering. This will happen because you are currently on that route.
//the route path can be defined like this:
localhost:123/#/userselection/:selectedid
When you navigate it will look something like this
localhost:123/#/userselection/1
localhost:123/#/userselection/2
localhost:123/#/userselection/3
etc.
//Now if you are on
localhost:123/#/userselection/2
and the User changes to selectionid 3, you will have to trigger a render
which is not usually desired behaviour
An idea may be to have some sort of ComponentStateService that is declared at a root level of your application. Use this Service to set and read desired state. So when the User selects something, have an Object with the Component Name, and its stateData.
export default class ComponentStateService{
_stateData = {};
constructor(defaultState = null){
if (defaultState){
this._stateData = defaultState;
}
}
getComponentStateData(componentName){
if (this._stateData){
return this._stateData[componentName];
}
}
setComponentStateData(componentName, stateData){
this._stateData[componentName] = stateData;
}
}
Then initialize it something like this at a high level:
import ComponentStateService from './componentStateService';
var componentState = new ComponentStateService(//default state passed in here);
export default componentState;
Then to use it, import it to each component
import componentState from '../index';
// call this to set the state
componentState.setComponentStateData("component1", {});
// and retrieve state
let savedState = componentState.getComponentStateData("component1");
Then you retrieve or update as necessary. You can make use of the LifeCycle Hooks that react has in order to read and set the data before the Comopnent is Rendered. Also you will need to ensure that you are correctly updating the data for the state upon User changing their selection.
As you can see though, the major flaw is you cannot share your link and expect someone else to see what you see, since it will persist in a Users Browser Session.
You can create a base class that imports this, so you don't have to import it every time.
You can also dump the entire state to local storage so it persists beyond a session, and load it up on app start
Related
I'm trying to prevent user from abandoning the page if he has some unsaved changes.
However, react router seems to trigger this prompt if the search params change, even if I am on the same page.
const navigation = useNavigation();
unstable_usePrompt({
when: didValuesChange(),
message:
"Are you sure you want to navigate away from this page? You have some unsaved changes!",
});
I need to check if the current url is the same as the next url without the search params and then skip the prompt, but I can't figure out how to do that.
useNavigation hook returns the location property which states: "This tells you what the next location is going to be."
However, it is always undefined when I try to navigate to other pages.
Docs
For example, setting "{activeTab: 9}" (with useSearchParams) params to "/tours/5" triggers the prompt that I am leaving the page. Even if it is the same page. How can I prevent that trigger by comparing the current route without params with the next route? (Or some other way)
React router v6.8.1
const notOnSamePage = () => {
//?
}
unstable_usePrompt({
when: didValuesChange() && notOnSamePage(),
message:
"Are you sure you want to navigate away from this page? You have some unsaved changes!",
I am working on an angular 2 application. I came across the following scenario:
The data to be shown on view is coming from API. There are some fields which can be modified from view and then saved using API calls. There is functionality of auto refresh every 30 seconds(API call to update the view with latest data). Now suppose the user has modified the editable fields and before submitting for save, the page is auto refreshed and the changes made by the user is lost.
What I want, is to save the data changed by the user so that there is no need to modify it again after auto refresh.
Suggest some efficient way to implement it.
Just declare a variable in your component for flag that user something changed. Your code will look like this:
export class YourComponent implements DoCheck{
isUserChanged: boolean;
// ngDoCheck will fire every time when change detection of Angular will fire
ngDoCheck() {
this.isUserChanged = true;
// make isUserChanged to false when you need to do it.
}
}
when isUserChanged will be true then you will not update your view with data.
Hope it will help
I have Redux app with React Router (based on https://github.com/este/este).
Inside one Route, there may be more than 1 AJAX calls (fired by redux-promise-middleware & redux-thunk). When the page changes (via react-router) I wish to reject all remaining _SUCESS or _FAILED callback actions fired by the previous route.
What is the best way to do this?
I'd suggest that you make the data you fetch page-aware. Meaning that in the action where the fetch is started, add a page-context. When the reducer gets the data it can either save it for that page-context or it can throw it away if the location is not the same as your browser (meaning that the user has navigated away). If you keep the data for the different pages/contexts you also have the bonus of these being ready if the user returns (if that is something that you'd want).
You are on url "/pageX". You start fetching data and the action makes sure that the page-context is remembered for when the SUCCESS action is to be dispatched. When the reducer handles the action it stores the data in store.context["/pageX"].data (or similar). Note: This is where you could also throw it away (reject) in case the current location is not the same as the received data.
The UI should know how to ask/use data from the context that matches it's location only.
You might also want to consider tracking the browser-location in the state for the app...
Ok so here is what is happening:
I have a client that I am building an application for. My client has a flowchart that they would like posted on the front page of their application. Check. My client then wants this flowchart to be set up as an image map so that a user could click one of the boxes in this flowchart and be taken to a report in another part of the application. Check.
All of that is elementary and, in a technical sense, works. The issue is, and it is an issue I have encountered before with APEX, is that every time a user clicks one of these links it takes them to the login screen. It seems that linking directly to a page's URL breaks the session and requires you to login again, even if you are linking from one page in the application to another in the same application.
I have played with all of the authentication settings in a hopes of fixing this and tried to determine what is breaking the session exactly but with no luck.
Has anyone else had this problem and could share their method for fixing it? I really cant have users logging in every time they click a link and I also cannot simply remove the authentication on the pages. Thanks in advance.
You should pass on the session id in your links. If you don't, then apex will see this as a new session. You can tell from the url: take note of the session id in your url when you are on your image map. When you select an application, take another look at the session id part in the url. If they are different, then you are starting a new session each time.
/apex/f?p=190:90:1674713700462259:::::
190 -> application id
90 -> page id
1674713700462259 -> Session id
To pass on the session, it depends where you construct your links.
In PLSQL, you can find it through :SESSION or :APP_SESSION
For example, in a plsql dynamic region: htp.p('the session id is '||:SESSION);
In javascript code you can use $v("pInstance") to retrieve the value dynamically, or use &APP_SESSION. which will have the value substituted at runtime.
Small example:
function printsome(){
var d = $("<div></div>");
d.text('&APP_SESSION. = ' + $v("pInstance"));
$("body").append(d);
};
So you probably just need to alter the construction of your link somewhat to include the session!
I was assuming the binding variables will do the job. But they were helpless.
Best way is to pass the current session id to an item then use the item value in the link.
f?p=&APP_ID.:32:&P31_SESSION.:::P32_CUSTOMER_ID:#CUSTOMER_ID#
I have a plugin and i need to load a different routing.yml file based on a variable in the query string.
Example:
if($request->getParameter('page'){
// use routingPage.yml
}
else{
// use another routing.yml
}
So, If the page parameter in url the url_for('#route1'), will return one url, else the same url_for('#route1') would return other url.
How can override the rouing.yml loading mechanism to do what I want?
Every application can have only one routing.yml (of course it can be overrided by other plugins).
The reason for this is quite simple: If you want to use multiple routing files (say routing1.yml and routing2.yml), and they both have a route called route1, which redirects to controller1/action and controller2/action respectively.
Maybe you would be able to switch it in the view, and go to controller1/action in the one case and controller2/action in the other. But then: when a new request arrives, and the front controller is determining which controller / action to execute: how does it now which routing.yml to use?
So I don't know exactly what you're trying to achieve, but I would go for two routes in your routing.yml, and select the route based on your view parameters.