I want to add a joyride or guided tour for my React App. I want to show it when the users first uses it and disable for subsequent frequent visits.
I have found this library https://github.com/gilbarbara/react-joyride but couldn't figure out how to disable on subsequent visits by same user?
Can I use localstorage or cookies to deal with this issue? How?
Yes adding it to localStorage is a good solution. I use the following function for this to trigger the check:
checkForInitialTour() {
if (!localStorage.getItem('tourDone')) {
localStorage.setItem('tourDone', true);
this.joyride.reset();
this.joyride.start(true);
}
}
Also possible to set in localstorage after tour by using the callback parameter
callback={(e) => { if (e.type === 'finished') { window.scrollTo(0, 0); localStorage.setItem('tourDone', true); } }}
If you're using nextjs or server-side rendering, here's my approach:
State is initialized:
runJoyride: (typeof window === 'undefined')? false : window.localStorage.getItem('onboarded') === null,
And you callback:
handleJoyrideCallback = data => {
const { action, index, status, type } = data;
if ([STATUS.FINISHED, STATUS.SKIPPED].includes(status)) {
this.setState({ runJoyride: false });
window.localStorage.setItem('onboarded', true);
}
};
Related
I'm using React js. I need to detect page refresh. When user hits refresh icon or press F5, I need to find out the event.
I tried with stackoverflow post by using javascript functions
I used javascript function beforeunload still no luck.
onUnload(event) {
alert('page Refreshed')
}
componentDidMount() {
window.addEventListener("beforeunload", this.onUnload)
}
componentWillUnmount() {
window.removeEventListener("beforeunload", this.onUnload)
}
here I have full code on stackblitz
If you're using React Hook, UseEffect you can put the below changes in your component. It worked for me
useEffect(() => {
window.addEventListener("beforeunload", alertUser);
return () => {
window.removeEventListener("beforeunload", alertUser);
};
}, []);
const alertUser = (e) => {
e.preventDefault();
e.returnValue = "";
};
Place this in the constructor:
if (window.performance) {
if (performance.navigation.type == 1) {
alert( "This page is reloaded" );
} else {
alert( "This page is not reloaded");
}
}
It will work, please see this example on stackblitz.
It is actually quite straightforward, this will add the default alert whenever you reload your page.
In this answer you will find:
Default usage
Alert with validation
1. Default Usage
Functional Component
useEffect(() => {
window.onbeforeunload = function() {
return true;
};
return () => {
window.onbeforeunload = null;
};
}, []);
Class Component
componentDidMount(){
window.onbeforeunload = function() {
return true;
};
}
componentDidUnmount(){
window.onbeforeunload = null;
}
2. Alert with validation
You can put validation to only add alert whenever the condition is true.
Functional Component
useEffect(() => {
if (condition) {
window.onbeforeunload = function() {
return true;
};
}
return () => {
window.onbeforeunload = null;
};
}, [condition]);
Class Component
componentDidMount(){
if (condition) {
window.onbeforeunload = function() {
return true;
};
}
}
componentDidUnmount(){
window.onbeforeunload = null;
}
Your code seems to be working just fine, your alert won't work because you aren't stopping the refresh. If you console.log('hello') the output is shown.
UPDATE ---
This should stop the user refreshing but it depends on what you want to happen.
componentDidMount() {
window.onbeforeunload = function() {
this.onUnload();
return "";
}.bind(this);
}
Unfortunately currently accepted answer cannot be more considered as acceptable since performance.navigation.type is deprecated
The newest API for that is experimental ATM.
As a workaround I can only suggest to save some value in redux (or whatever you use) store to indicate state after reload and on first route change update it to indicate that route was changed not because of refresh.
If you are using either REDUX or CONTEXT API then its quite easy. You can check the REDUX or CONTEXT state variables. When the user refreshes the page it reset the CONTEXT or REDUX state and you have to set them manually again. So if they are not set or equal to the initial value which you have given then you can assume that the page is refreshed.
How can I catch with serviceworker or simple js code, when user who previously allowed the web push notifications for my site disable them? For Firefox and Chrome browsers.
You can use the Permissions API to detect the current state of given permissions, as well as listen for changes.
This article has more detail. Here's a relevant code snippet:
navigator.permissions.query({name: 'push'}).then(function(status) {
// Initial permission status is `status.state`
status.onchange = function() {
// Status changed to `this.state`
};
});
You can try this:
navigator.permissions.query({name:'notifications'}).then(function(status) {
//alert(status.state); // status.state == { "prompt", "granted", "denied" }
status.onchange = function() {
if(this.state=="denied" || this.state=="prompt"){ push_unsubscribe(); }
};
});
or this:
navigator.permissions.query({name:'push', userVisibleOnly:true}).then(function(status) {
//alert(status.state); // status.state == { "prompt", "granted", "denied" }
status.onchange = function() {
if(this.state=="denied" || this.state=="prompt"){ push_unsubscribe(); }
};
});
I use it to send information to the server that the user has canceled or disabled notifications. Note that the code is not executed if the user does so in the site settings.
I'm having two pages: my-view1 and my-view2.
On my-view1 I have two buttons that add and remove data from LocalStorage.
On my-view2 I have two simple div's that READ (display) total value, and total in last 6 months value.
However, on the second page, the value will not update if the page is not refreshed. I want the values from my-view2 to be automatically updated everytime the page is loaded (viewed, even if cached).
Here is a plnkr with my-view2 so you can undestrand what I'm trying to do.
https://plnkr.co/edit/ul4T2mduxjElCN4rUUKd?p=info
How can I do this?
You can listen to the storage event to trigger and update some prop in my-view2 when you update localStorage:
<my-view-2 id="myView2"></my-view-2>
<script>
window.onstorage = function(e) {
if (e.key !== 'someKeyYouWant') return;
document.getElementById('myView2').set('someProp', {
oldValue: e.oldValue,
newValue: e.newValue
});
};
</script>
EDIT (working plunk): Because of a behavior described here the storage event will not be triggered on the window originating the change, so you have to trigger your own storage event, consider the method below:
saveToLs(e) {
e.preventDefault();
const newName = this.get('dogName');
const ls = window.localStorage;
const synthEvent = new StorageEvent('storage');
const eventConfig = [
'storage',
true,
true,
'myDog',
ls.getItem('myDog'),
newName
];
synthEvent.initStorageEvent(...eventConfig);
setTimeout((() => { // ensure async queue
ls.setItem('myDog', newName);
this.dispatchEvent(synthEvent);
}).bind(this), 0);
}
...and on the listening side:
handleStorageUpdate(e) {
if (e.key !== 'myDog' || e.newValue === this.get('dogName')) return;
this.set('dogName', e.newValue);
}
Please note the if conditional handling potential duplicate updates with the same value.
Here is a working plunk for you to play with
I am using twilio API to implement screen sharing in an emberjs app, I am successfully able to share the screen and also toggle on stopping it. Here is my code ->
this.get('detectRtc').isChromeExtensionAvailable(available => {
if (available) {
const { twilioParticipant } = this.get('participant')
if (this.get('stream') && this.get('stream').active) {
this.get('streamTrack').stop()
this.get('userMedia.mediaStream')
.removeTrack(this.get('streamTrack'))
this.set('isEnabled', false)
twilioParticipant.removeTrack(this.get('streamTrack'))
} else {
this.get('detectRtc').getSourceId(sourceId => {
// "cancel" button is clicked
if (sourceId !== 'PermissionDeniedError') {
// "share" button is clicked extension returns sourceId
this.get('userMedia')
.getScreen(sourceId)
.then(mediaStream => {
this.set('isEnabled', true)
this.set('stream', mediaStream)
this.set('streamTrack', mediaStream.getVideoTracks()[0])
twilioParticipant.addTrack(mediaStream.getVideoTracks()[0])
})
.catch(() => { /* do nothing, but return something */ })
}
})
}
} else {
this.get('flash').status(
'base',
this.get('intl').t('chromeExtension.install'),
{
icon: 'alert-circle',
push: true
}
)
// TODO Show the system popup to install chrome extension from web store
// !!chrome.webstore &&
// !!chrome.webstore.install &&
// chrome.webstore.install(this.webStoreUrl)
}
})
The issue I'm facing is with the stop sharing button which is at the bottom of the app as seen in screenshot below
I need a way to listen to an event handler and execute the some code after clicking on the stop sharing screen button, I know there is an onended event Handler which is mentioned in the MediaStreamTrack docs, but I don't know how to use it, any help will be highly appreciated.
https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack
The "stop sharing" button will trigger the MediaStreamTracks 'ended' event. Try this:
mediaStream.getVideoTracks()[0].addEventListener('ended', () => console.log('screensharing has ended'))
for some reason, #philipp answer is not working for me and I found this quite helpful
https://github.com/webrtc/samples/blob/gh-pages/src/content/getusermedia/getdisplaymedia/js/main.js#L88
this.get('stream').addEventListener('inactive', e => {
console.log('Capture stream inactive - stop recording!');
});
I have a google sign-in button on my page, using gapi.signin2.render to render the button (https://developers.google.com/identity/sign-in/web/reference#gapisignin2renderid-options).
However it ALWAYS renders as signed-in, despite calling GoogleAuth.signOut(). In fact I can actually call GoogleAuth.signOut() and immediatly check GoogleAuth.isSignedIn.get() to check the state and returns as true.
Does anyone know how to fix this? My sign-out code is as follows:
var GoogleAuth = gapi.auth2.getAuthInstance();
GoogleAuth.signOut().then(() => {
var status = GoogleAuth.isSignedIn.get(); //ALWAYS TRUE!!!!
alert('IP.common.oAuth.signOut: signin status: ' + status);
});
This should be work fine. Delete then(this.props.onLogoutSuccess)) if you don't need it.
signOut() {
if (window.gapi) {
const auth2 = window.gapi.auth2.getAuthInstance()
if (auth2 != null) {
auth2.signOut().then(auth2.disconnect().then(this.props.onLogoutSuccess))
}
}
}
Very nice lib, if you wanna learn how to work with Google API https://github.com/anthonyjgrove/react-google-login. Yes it's react, but methods should be similar, I think.