Cannot register Service Worker in React script - reactjs

I am making a basic web app with ReactJS to create push notifications.
I want to let the user the possibility to register manually the service worker by clicking on a button. But nothings happens (no message of success in the console). Did I make a mistake somewhere?
In a standard js file, the code to register the service worker works (without the button though) , but not in the react file.
the code to register the service worker :
and the event listener on the button :
Thanks in advance !

The main issue I see is that you attach an EventListener to window that would execute on 'load'. Since this event is most likely already triggered since you can click on a button, the SW is not getting loaded.
Try removing the eventhandler part to directly call the register function.
It would then look something like this:
function registerSW() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('sw.js')
//...
}
}
Another issue I see is that you try to set state by directly assigning it. In react you shouldn't access state like that but rather call this.setState like this:
// ...
.then(swReg => {
console.log('SW registered');
this.setState({ swReg: swReg });
})
// ...

Related

How to cancel a specific firestore realtime listener with a button in react native?

I'm using a realtime listener on a firestore collection to get the latest data. The function I'm using is like below,the function is attached to a button press.
function getItems(selectedCategory){
const subscriber = firestore()
.collection('CollectionName')
.doc('documentName')
.collection('CollectionName2')
.where("category", "==", selectedCategory)
.onSnapshot(documentSnapshot => {
console.log('Total Docs: ', documentSnapshot.size)
documentSnapshot.forEach(documentSnapshot => {
console.log('doc ID: ', documentSnapshot.id);
});
});
unSubscriptions.push(subscriber); //to detach the listener when page is changed(usefocuseffect)
}
when I call the function I can get the results and render them accordingly. But if I invoke the function again with a different input variable for "selectedCategory" it also logs the results. The thing is if any changes happened with the first occurrence (the first input variable) it also gets logged. I believe this happens because the listener for the first input parameter is still being active. Is there a way I can detach the first listener before invoking a second one.
P.S : I'm using a return function with useFocusEffect to cleanup the listeners when the page goes out of focus(which works) but I want to do a similar thing with a button press.
onSnapshot() returns a function that you need to call to detach your listener.
So you need to simply do subscriber() (note the parentheses) when clicking your button.
The specific doc is here.

icpRenderer.on not firing on React side of app

I am using Electron do make a desktop version on my Ionic React app. I've decided that the splash screen is only going to disappear when the React app says it can.
In index.ts (the main Electron file), I create an event listener like this:
ev = splashScreen.on(splashScreen.events.APP_READY_TO_START, () => {
splashScreen.off(ev, true);
splashScreen.destroy();
mainWindow.show();
}, true);
This listens for the OL-APP_START_SPLASH_CLOSE event through ipcMain. The on function looks like this:
on(event: string, fn: () => any, isExternal?: boolean) {
this.activeEvents.push({
[isExternal ? "EXTERNAL_" + event : event]: fn
});
if (isExternal) ipcMain.on(event, fn);
}
Following the event listener, I call an update function which (temporarily) delays execution for 7 seconds. After that, I emit an event:
splashScreen.emit(splashScreen.events.UPDATE_CHECK_FINISHED, true);
where emit is:
emit(event: string, isExternal?: Boolean) {
this.activeEvents.forEach(e => {
if (!Object.keys(e)[0].startsWith("EXTERNAL_")) e[event].bind(this).call(); //If it's an external event (i.e. `ipcMain`) then don't run callback
});
if (isExternal) this.splashScreen.webContents.send(event);
}
On the React side, in componentDidMount I have:
ipc.on("OL-CHECKED_FOR_UPDATES", () => {
ipc.send("OL-APP_START_SPLASH_CLOSE");
});
This will signal the splash screen to close only when updates have finished being checked for. When I emit the OL-CHECKED_FOR_UPDATES event this event listener should be called however it isn't.
I am able to send events fine (ipc.send works on it's own) but no matter what I do, I can't get it to listen for events.
I know these are being fired because if I move the event listener into any other script (ie index.ts) the event listener will fire, so it is only there it won't fire.
What could be the reason for this?
Just needed to sleep on it. Of course, if I create two different windows, they're going to have different render processes so when I emit an event on one, I'm not going to be able to receive it on the other.
All I had to do was send the event from the main window (the one displaying the react app) instead of the splash screen.

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
}

Test fails because AngularJS has not initialized in time

I'm trying out TestCafe for an AngularJS (v1.6) application.
I have a button then when clicked, opens a modal (from UI bootstrap). This works fine when I try myself in Chrome.
<button class="btn" ng-click="open()">Open</button>
Our application requires user authentication, and the login page is not Angular-based. That phase of my test works fine.
However, when the actual test runs, it "clicks" the button but nothing happens.
I suspect, but can't prove, that it's clicked before AngularJS has properly initialized on the page.
With some research, I found the testcafe-angular-selectors project and a waitForAngular method but that appears to apply only to Angular2+.
import { Role, Selector } from 'testcafe';
const regularAccUser = Role('http://127.0.0.1:8080', async t => {
await t
.typeText('[name=username]', 'abc')
.typeText('[name=password]', '123')
.click('.btn-primary');
});
fixture`Characters Modal`;
test('modal title', async t => {
await t
.useRole(regularAccUser)
.navigateTo('http://127.0.0.1:8080/fake/page')
.click('.btn')
.expect(Selector('.modal-title').innerText).eql('Insert Symbol');
});
Adding .wait(1000) before the click solves the issue. It's not waiting for Angular to load. I'd rather not have waits in every test - is there some other technique I can use?
You can use TestCafe assertions as a mechanism to wait until an element is ready before acting on it.
A typical waiting mechanism would be:
const button = Selector('button.btn')
.with({visibilityCheck: true});
await t
.expect(button.exists) // wait until component is mounted in DOM
.ok({timeout: 10000}) // wait enough time
.hover(button) // move TestCafe cursor over the component
.expect(button.hasAttribute('disabled'))
.notOk({timeout: 10000}) // wait until the button is enabled
.click(button); // now we are sure the button is there and is clickable
This article may also help you in managing all those waiting mechanisms.
As you correctly mentioned, the waitForAngular method is intended for Angular only, not for AngularJS.
I recommend you create your own waitForAngularJS function and call it on the beforeEach hook and after the role was initialized.
In the simplest case, it can be implemented as follows:
function waitForAngularJS (t) {
await t.wait(1000);
}
fixture `App tests`
.page('page with angularjs')
.beforeEach(async t => {
await waitForAngularJS(t);
});
However, the use of the wait method is not a solid solution. I recommend you find a way to detect if AngularJS is loaded on a page on the client side. If it is possible, you can implement the waitForAngularJS method using the TestCafe ClientFunctions mechanism.
This post can be usefulĀ as well: How to check if angular is loaded correctly

React Create Portal event listening

So I am trying to migrate an existing Portal implementation from the old unstable_renderSubtreeIntoContainer to the new portal implementation.
I have an issue though, the relevant code has the following functionality:
unstable_renderSubtreeIntoContainer(
this,
this.props.children,
this.portalElement,
() => {
if (this.props.isOpen) {
this.props.onRender(this.portalElement,
this.getTargetElement());
}
callback(); //runs this.props.open() if the update ran open
},
);
Some of the open/close logic could be simplified by wrapping the component to be rendered inside an object and the appropriate callbacks could be called from there. But it seems createPortal has no callback to allow you specify when a render has or hasn't taken place. Is there anyway to synchronously or asynchronously on a createPortal call has finished rendering?

Resources