React - detect if page routing was triggered by keyboard press - reactjs

I am using React 17 and react-router-dom 5.2.
I have a left sidebar and a main content area.
Each page opened directly via URL, or via click on a link in the navbar it opens a page.
Each page has an entry route such as:
<Route path="/testpage" component={TestComponent} />
I need to detect if a person entered the page via keyboard or via some other way (mouse click, or direct url entered).
Each compnent has a header:
If a person enters via mouse click or entering the direct URL in the browser nothing changes.
If the person clicked the TAB key until the right link is focused in the navbar, and then the person presses ENTER in the keyboard, the page changes.
And in this case the tabindex should be 1 - <TestHeader title="" tabIndex={0} />
I am wondering how can I create a state in this component that holds the information if the page was loaded via keybaord or not...
Ideally I would have that line as the following:
<TestHeader title="" tabIndex={enteredByKeyboard ? 1 : 0} />
I hope somebody can help

To acknowledge if the user has pressed "Enter" key can be achieved via listening to keypress event. The addional logic can take place after the key press is captured.
// Execute a function when the user presses a key on the keyboard
input.addEventListener("keypress", function(event) {
// If the user presses the "Enter" key on the keyboard
if (event.key === "Enter") {
// Cancel the default action, if needed
event.preventDefault();
// Trigger the button element with a click
document.getElementById("myBtn").click();
// run the custom logic
// extract this line at the component level,
// (as the effects can only be utilised there
// const navigate = useNavigate();
const calculateRequiredRoute = event.target.value;
// modify the line above to achieve the desired name of that route
navigate(calculateRequiredRoute);
}
});
This way it would
Refer :
https://reactrouter.com/en/main/components/navigate
https://reactrouter.com/en/main/hooks/use-navigate
Edit:
keydown event can be used for better result, just when the key press was down, instead of on release of the pressed-key.

Related

Updating a state array while avoid rerenders in React

I'm building a project in react native. I have a dynamic list of players, that I want the user to be able to edit.
const [players, setPlayers] = useState(['']);
function addPlayer() {
setPlayers([...players, '']);
}
...
<List>
{ players.map(player => (
<MyInput ...>
)}
</List>
What I want to achieve is this:
User enters name
User presses enter
We call addPlayer which adds a player
New input appears and gets focused on (by other functions).
What I get is this:
User enters name
User presses enter
We call addPlayer which adds a player
The Keyboard starts closing for a split second and then opens back up when the new input appears.
I have set blurOnSubmit to false on my inputs. In my opinion what happens is that the list gets rerendered, causing the keyboard to dismiss itself. Then when the setPlayers finishes executing (it's async), the focus function gets called
useEffect(() => {
if (lastRef.current) {
lastRef.current.focus();
}
}, [players]);
What is the best way to stop the list from rerendering so that the keyboard can stay open the whole time ? Thanks !
In the end I cheated, I added an input that’s sitting right outside the list. I can control whether it’s shown or not, it’s content, as well as it’s color with other state variables.
That way when a player is added the list rerenders but doesn’t affect my input, and my keyboard doesn’t move.
From a users POV it looks exactly the same as it did before, as if he’s editing items directly in the list.

How to call or pass method from Screen B to Screen A in react native?

I have two screens, Screen A and Screen B. In which screen B has a state which needs to be passed to Screen A and i have achieved that using react navigation by sending params via navigation. The problem is i need to call a method is Screen A when a button is clicked in Screen B ( when the button is clicked it navigates to Screen A ) and along with navigation ends i need to call a method to perform setState.
How to achieve this ?
My Method:
handler(){
this.setState({ visible: !this.state.visible })
}
So when user clicks on a button ("Apply") in Screen B the button will call navigation. So how to call handler() when user clicks on button at Screen B ?
I believe the best approach, using navigation params, is to put a condition in the componentDidMount of screenA calling your handler() if you detect that the param you sent from screenB exists. Something like this (not sure about the exactly writing):
screenB
this.props.navigation.navigate('screenA', { paramFromB: 'param passed from Screen B'}
screenA
componentDidMout(){
if(this.props.navigation.state.params.paramFromB){
this.handler()
}
}
so every time you enter in screen A it will check if the param from screen B exists and then call your handler

ReactJS console.log disappearing after some second

I am implementing SSO in my reactjs app on a button click and debugging one error by adding console.log to see the this.props.location variable. But as I click on the auth me button (that will trigger the sso auth) it shows the log for few second and then disappear. I have taken printscreen
I want to expand the object in console and view the attributes value , but unable to do it as it is disappearing. I have added wait timers also to hold the block but its getting hanged. Is there is a better way so that I can log the console.log's data to a file and view the errors peacefully without getting in a rush.
You have to use this code inside your submit button to prevent the default submit event.
onSubmitClicked = (e) => {
e.preventDefault()
//additional codes
}

React-Router v4 - Prevent Transition With Function

I was able to prevent navigation as per the v4 docs, but I'm trying to hook up a function so that I can use a modal instead of an alert.
Function:
abandonForm = (route) => {
this.props.showModal('confirm');
console.log('leaving..');
}
In my page:
<NavigationPrompt when={true} message={(location) => this.abandonForm('confirm')} />
this.props.showModal('confirm') activates the modal successfully, but behind the modal the page still transitions - how can I prevent transition until a button in the modal is clicked?
Browsers only allow navigation cancellation by means of the alert box that you've mentioned. This restriction is motivated by phishing/scamming sites that try to use javascript gimmicks to create user experiences that convincingly mimic something that a browser or the OS would do (whom the user trusts). Even the format of the text shown in the alert box is crafted so that it's obvious that it originates from the site.
Of course, as long as the current URL stays within your app, you have control over it using react-router's history. For example you can do the following on navigation:
allow the navigation without confirmation
immediately navigate back to the previous location, but now with a modal on top
navigate away for real this time when the user clicks on a button in the modal.
The disadvantage of this approach (leaving out the sheer complexity of it) is that the user will not get a confirmation dialog if they try to navigate to a different site entirely.
Use:
this.unBlock = this.props.history.block((location, navigateToSelectedRoute) => {
// save navigateToSelectedRoute eg this.navigateToSelectedRoute =
// navigateToSelectedRoute;
// use this.navigateToSelectedRoute() afterwards to navigate to link
// show custom modal using setState
});
and when unblocking is done then call this.unBlock() to remove the listener.
Documentation here for history api

back button navigation alert user

If the user presses the back button, i am displaying a confirm dialog. Based on the user choice in the dialog, navigation is prevented or continues.
Here is the code for the same:
$rootScope.$on('$stateChangeStart', function(e) {
if(confirm('u want to leave the page?') != true){
e.preventDefault();
}
});
its working fine. The problem i have is, lets say,
The user is in 'Page2' when he presses the back button(he came there from Page0 -> Page1 -> Page2), user stays in 'Page2' if he chooses cancel in the dialog. But when he presses back button again, it takes him to 'Page0'.
I need to keep the history from changing if he chooses to not navigate back in the dialog.
How can i achieve this?
Thanks in advance.
Consider using
window.history.back()
window.history.forward();
In order to navigate Browser History.
Full API is described here:
https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history

Resources